home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-2.iso / os2 / edmi3_9.zip / edmi3-9.INF (.txt) < prev    next >
OS/2 Help File  |  1995-11-06  |  380KB  |  4,684 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Nov 1995 Title Page ΓòÉΓòÉΓòÉ
  3.  
  4.                   The Electronic Developer's Magazine for OS/2
  5.                       Portions copyright (c) by IQPac Inc.
  6.                                 Volume 3, issue 9
  7.  
  8. Administrivia 
  9.  
  10. EDM/2 3-9 is finally out!  Last month, I was extremely busy with many things, 
  11. not the least of which were preparing for ColoradOS/2 and converting old issues 
  12. to native HTML format, so I passed the ball to Carsten. Unfortunately, Carsten 
  13. never produced an entire issue, so after much trial and error and with what 
  14. little help I could offer from Colorado, he finished after October 15; we 
  15. decided that, given the slimness of the issue, we would push it to November 
  16. since we were expecting more submissions from other authors. 
  17.  
  18. A few notes before I sign off for the month: 
  19.  
  20.      In the mailing list, we are conducting an impromptu vote regarding the 
  21.       format that you would prefer the magazine to be published in.  The 
  22.       choices are HTML, INF, or "other".  The results will have some influence, 
  23.       but do not assume that they will completely influence our direction.  I 
  24.       highly suggest that you send me email (os2man@panix.com) to let me know 
  25.       which you prefer. 
  26.  
  27.      The Web site is growing rapidly!  Issues 3-5 through this one are now 
  28.       present in native, well-organized HTML format.  Additionally, a new 
  29.       Content Index has been added to allow you to browse a list of all of the 
  30.       available submissions and follow the appropriate link when you've found 
  31.       what you're looking for.  We're excited about this and plan to enhance it 
  32.       in different ways to make it as useful as possible for you. 
  33.  
  34.      Also on the Web site are my notes from ColoradOS/2.  If you weren't able 
  35.       to attend, you can still read about the things you should have seen and 
  36.       heard during that week. 
  37.  
  38.  Carsten, assuming the role of publisher, wrote this section originally and his 
  39.  text is below.  Enjoy! 
  40.  
  41.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  42.  
  43.  Well, this month the worst finally happened:  Larry got too busy doing other 
  44.  important things (among which is converting old issues to HTML!) to do this 
  45.  issue, so here I am, starting late, and going slow.  It has been a long and 
  46.  hard month, but there were a few highlights. 
  47.  
  48.  Already there are many reports of people buying some other 32-bit operating 
  49.  system, and getting so disappointed that they took it back and bought Warp. Of 
  50.  course, this is not what everyone is doing, but every little bit helps.  We 
  51.  need to be ready for these people with lots of great high-quality OS/2 apps, 
  52.  so everybody get cracking right now! 
  53.  
  54.  A new fixpack (10) is out, and it has received mixed reviews.  There are also 
  55.  two unauthorized fixpacks out there (11 and 12), and although I wouldn't 
  56.  recommend an unauthorized fixpack, it sounds as if things are heading in the 
  57.  right direction.  Fixpacks 9 and 10 broke some things in the REXX DLL, but 
  58.  supposedly these are fixed again in fixpack 12.  One of the things which was 
  59.  broken in 9 and 10 was the VRPrompt function in VX-REXX, which uses an 
  60.  automatically sized entry field.  It turns out that the entry field itself was 
  61.  broken, and IBM seems to have admitted this.  Hence the re-fix in fixpack 12. 
  62.  
  63.  Included with this issue is the latest round of bugfixes and updates for the 
  64.  editor which has been developed in the last few issues.  Look for 
  65.  smaled95.zip. 
  66.  
  67.  If the format is a little odd here and there, it is because I didn't have time 
  68.  to go around and fix everything.  It should be readable, though.  That is 
  69.  about all I have to say here.  Now we continue on with the rest of this 
  70.  slightly slim issue... 
  71.  
  72.  Title Page - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  73.  
  74.  
  75. ΓòÉΓòÉΓòÉ 2. Copyright Notice ΓòÉΓòÉΓòÉ
  76.  
  77. Copyright Notice 
  78.  
  79. EDM/2 is published by IQPac Inc.  IQPac Inc. can be reached via U.S. Mail at 
  80. the following address: 
  81.  
  82. IQPac Inc.
  83. 7 East Broadway, Box 804
  84. New York, NY 10038
  85. U.S.A.
  86.  
  87.  Editor-in-chief     Larry Salomon Jr. 
  88.  Associate editor    Carsten Whimster 
  89.  Contributing editor Gordon Zeglinski 
  90.  
  91.  CEO/President       Larry Salomon Jr. 
  92.  
  93.  All material is copyrighted by its original author.  No part of this magazine 
  94.  may be reproduced without permission from the original author. 
  95.  
  96.  This publication may be freely distributed in electronic form provided that 
  97.  all parts are present in their original unmodified form.  A reasonable fee may 
  98.  be charged for the physical act of distribution; no fee may be charged for the 
  99.  publication itself. 
  100.  
  101.  Neither IQPac Inc. nor this publication are affiliated with International 
  102.  Business Machines Corporation. 
  103.  
  104.  OS/2 is a registered trademark of International Business Machines Corporation. 
  105.  Other trademarks are property of their respective owners.  Any mention of a 
  106.  product in this publication does not constitute an endorsement or affiliation 
  107.  unless specifically stated in the text. 
  108.  
  109.  The OS/2 Accredited Logo is a trademark of International Business Machines 
  110.  Corporation and is used by IQPac Inc. under license.  This On-line Publication 
  111.  is independently produced by IQPac Inc. and IBM is not responsible in any way 
  112.  for its contents. 
  113.  
  114.  IQPac Inc. is an accredited member of the IBM Independent Vendor League. 
  115.  
  116.  Copyright Notice - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  117.  
  118.  
  119. ΓòÉΓòÉΓòÉ 3. Letters ΓòÉΓòÉΓòÉ
  120.  
  121. Letters 
  122.  
  123. To write to EDM/2, send your email to os2man@panix.com and use the Subject: 
  124. line "Letters". 
  125.  
  126. Appreciations! 
  127.  
  128. Kalin Wilson (kwilson@mnsinc.com) writes: 
  129.  
  130. Just wanted to send along my appreciation for your great product! I have been 
  131. reading your magazine for several months now and have managed to catch up on 
  132. many of the back issues.  I have really learned a lot. I think I get more out 
  133. of EDM/2 than OS/2 Developer or any other programming mag I get. Your web page 
  134. is a big bonus. I have been archiving all the issues not on my Hobbes CDROM but 
  135. it's nice to know I can get any issue from the web site. 
  136.  
  137. You're on my hotlist! 
  138.  
  139. EDM/2 (Carsten) Responds: 
  140.  
  141. That's the same way I felt about EDM/2 when I first started reading it. I hope 
  142. we can continue to provide this kind of service to OS/2 programmers everywhere, 
  143. and if you should ever want to contribute an article or a column, you know 
  144. where to reach us. 
  145.  
  146. Thank you! 
  147.  
  148. Niall Kavanagh (niall@peersa.iii.net) writes: 
  149.  
  150. Just a quick note to say "Thank you!". Armed with EDM/2- Intro. to PM 
  151. programming and _Real World Programming for OS/2_ I have successfully completed 
  152. my first PM application! Keep up the great work! 
  153.  
  154. EDM/2 (Carsten) Responds: 
  155.  
  156. That is also one of my favorite books. There are other great ones, though. Be 
  157. sure to check the book review column from time to time. So, can we see your 
  158. program? <grin> 
  159.  
  160. Letters - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  161.  
  162.  
  163. ΓòÉΓòÉΓòÉ 4. Announcements ΓòÉΓòÉΓòÉ
  164.  
  165. Announcements 
  166.  
  167. Bullet Database Engine Toolkit for 32-bit Compilers 
  168.  
  169. Contact:  Cornel Huth
  170. /e-mail:  cornel@crl.com
  171.  
  172. San Antonio, Texas - Bullet/2 for OS/2 is a thread-safe, multi-process capable 
  173. database engine toolkit.  It provides pre-built and tested access methods to 
  174. data and index files for application programmers.  It is not an end-user 
  175. Database Management System (DBMS), but it is a tool that may be used to develop 
  176. one.  Bullet is compact, efficient, and very fast.  Bullet can be configured to 
  177. use custom key-build, sort-compare, and expression- parser routines to extend 
  178. the built-in functionality.  Rules are few; possibilities are great. 
  179.  
  180. The standard data format is DBF (dBASE 3+ and later).  The supported memo 
  181. format is DBT (dBASE 4 and later).  Index-only support can be enabled and with 
  182. this any data file format may be used (the data maintained by the programmer 
  183. then).  Also, the DBF standard may be extended by using binary field values and 
  184. fields larger than 255 bytes.  Index files are NLS- compatible and use an 
  185. efficient b-tree structure.  Files may be any size supported by the OS, up to 
  186. 4GB.  Up to 1024 files may be opened and in use by any one process, with any 
  187. number of processes active. 
  188.  
  189. The Bullet API consists of a wide assortment of routines, from low-level OS 
  190. calls to high-level transaction-list routines that can process hundreds of 
  191. files per transaction, with roll-back on error.  Network and multi-user support 
  192. is included, and makes use of operating system features such as atomic 
  193. re-locking, and shared locks that allow other processes read-access to locked 
  194. files. 
  195.  
  196. Bullet is simple to use and works the way you are used to working. 
  197. Documentation and samples included are for C or C++ compilers, but any compiler 
  198. supporting 32-bit DLLs may be used. 
  199.  
  200. Pricing is available in three options, depending on total open files needed, 
  201. simultaneous processes running, and DLL or LIB requirements.  Price starts at 
  202. $99 US.  This release includes a try-before-you-buy version with the same 
  203. functionality as is available in the $99 option (100 open files, 2 processes), 
  204. and may be used for evaluating Bullet before purchase.  The try-before-you- buy 
  205. version for OS/2 is located at the following locations: 
  206.  
  207.      FTP: - ftp.crl.com  /users/co/cornel/database/blt2_203.zip 
  208.      WWW: - ftp://ftp.crl.com/users/co/cornel/database/blt2_203.zip 
  209.      BBS: - 1(210)684-8065 after business hours only ( 5pm-9am Central) 
  210.  
  211.  The filename is currently blt2_203.zip, but the last three digits will change 
  212.  with future releases.  Alternate sites include the SimTel archives (primary 
  213.  site being oak.oakland.edu), Hobbes (hobbes.nmsu.edu), and on CompuServe, to 
  214.  name a few.  Check the language and database directories for Bullet (blt*). 
  215.  
  216.  Bullet is now available for: 
  217.  
  218.  Bullet/2 for OS/2:  Includes DLL, import library, online and printer-ready 
  219.  manuals.  The API reference is available in either manual, with the tutorial 
  220.  and additional source examples in the online version.  A demo EXE program, 
  221.  along with source, is also included.  Printed documentation and the LIB 
  222.  version of the library code are also available. 
  223.  
  224.  Bullet/X for 32-bit DOS extenders is to be available by the end of the month 
  225.  and offers essentially the same features as Bullet/2, except it is for MS-DOS 
  226.  platforms (DOS extender/DPMI-compliant).  The Windows Win32 version is to 
  227.  follow soon after. 
  228.  
  229.  Bullet 1 has been available for 16-bit compilers since 1992, and these are 
  230.  available today as bltc125.zip, bltw125.zip, and bltq125.zip, for DOS C/C++, 
  231.  Window 3.x, and DOS BASIC compilers, respectively, at the sites listed above. 
  232.  For more information, visit any of the sites listed and download the 
  233.  evaluation files, or e-mail to cornel@crl.com. 
  234.  
  235.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  236.  
  237.  Multi-Voice and Multi-Fax Toolkit Released 
  238.  
  239.  Montreal, September 1995: 
  240.  
  241.  ITI Logiciel (ITI Software) announce the release of the OS/2 version of their 
  242.  Multi-Voice and Multi-Fax programmer's toolkit. 
  243.  
  244.  Multi-Voice and Multi-Fax can be used to create voice processing application 
  245.  such as:  voice mail, automated attendant, fax-on-demand, fax broadcasting, 
  246.  interactive voice response.  As a high level 'C' toolkit, it is as easy to use 
  247.  as any script language, but offers speed and flexibility of the 'C' language. 
  248.  
  249.  Here's description of the two products. 
  250.  
  251.  Multi-Voice Version 4.0 
  252.  
  253.  ITI Software proudly presents MULTI-VOICE Version 4.0, the complete set of 
  254.  tools to write multi-line voice applications on OS/2 for most of the voice 
  255.  processing boards available today. 
  256.  
  257.  Multi-Voice Product Description 
  258.  
  259.  MULTI-VOICE gives you a very high level C interface to the voice board 
  260.  features.  With a single function call, you can play or record a voice file. 
  261.  You can play date and time, numbers, spell strings.  Your Multi-Voice programs 
  262.  can detect the callers Touch-Tones or rotary pulses, even voice recognition is 
  263.  available in some versions.  Never before has it been easier to integrate a 
  264.  multi-line telephone interface to your C programs. 
  265.  
  266.  MULTI-VOICE has its own multi-tasking interface.  You can run the same task on 
  267.  all lines in the system or different tasks on certain lines.  For most 
  268.  applications, the multi-tasking is completely transparent and there is no need 
  269.  for the programmer to have multi-tasking programming experience. 
  270.  
  271.  MULTI-VOICE brings the full power of voice processing boards to your finger 
  272.  tips with the speed and ease of use of Borland's C/C++ 2.0 for OS/2. 
  273.  
  274.  Multi-Voice Example Programs 
  275.  
  276.  A Multi-User Multi-Line Telephone Answering program is provided to give 
  277.  examples of how to call most functions in the library.  The source code is 
  278.  included, so this program can be modified to suit your own needs.  We also 
  279.  provide all the pre-recorded prompts used by this program.  Many other example 
  280.  programs are also provided with makefiles for all supported compilers. 
  281.  
  282.  Voice Boards Supported 
  283.  
  284.  Dialogic D4xx, D12xx, AMX, VRxxx Rhetorex RDSPxxxx NewVoice NVx00 Bicom xLS 
  285.  Linkon's FC3000 &  FC4000 Pika's V12 and InLine Series Talking Technology's 
  286.  Power Line II 
  287.  
  288.  Portability 
  289.  
  290.  The programs written with Multi-Voice for any voice board can be ported 
  291.  without any modifications for use with other voice boards.  ITI Software 
  292.  offers C libraries for all the supported boards, which reduces the 
  293.  programmer's work to simply recompiling programs for the appropriate hardware. 
  294.  And we're always working to implement new manufacturer's products. 
  295.  
  296.  System Requirements 
  297.  
  298.  IBM PC or compatible running DOS 3.3 or higher (6.2 recommended) Any of the 
  299.  supported Voice Processing boards C/C++ Compiler:  Borland's V2.0 for OS/2 
  300.  
  301.  Talking Clock Sample Program 
  302.  
  303.   /*
  304.   ** This example program shows how easy and clear it is to program
  305.   ** Multi-Line Voice Response applications using MULTI-VOICE Version 4.0.
  306.   **
  307.   ** The program plays the current date and time on all lines available in
  308.   ** the system.  It answers the phone, plays a little introduction message,
  309.   ** asks the user to press 1 for FRENCH, 2 for ENGLISH or 3 for SPANISH
  310.   ** and it plays the  date and time in the selected language, in the format
  311.   ** Week Day, Month Day, Hour and Minutes.
  312.   */
  313.  
  314.   #include "stdio.h"
  315.   #include "MV_Util.h"
  316.   #include "MultiVox.h"
  317.  
  318.   #define TIMEOUT     10
  319.   #define RETRY       3
  320.   #define PROMPT_DIR  "PROMPTS"
  321.  
  322.   void far LineHandler ( )
  323.   {
  324.     char           answer;
  325.     MVU_LANGUAGE   language;
  326.     MVU_DATE       date;
  327.     MVU_DATE_FIELD date_field;
  328.  
  329.     MV_StartLH ( );
  330.  
  331.     while (MV_Running)
  332.     {
  333.       MV_Answer (1);           /* answer phone after 1 ring */
  334.  
  335.       if (MV_Result ( ) == MV_SUCCESS)
  336.       {
  337.         MV_Play ("intro.v", MV_AbortOnDtmf);
  338.  
  339.         MVU_ReadMenu (PROMPT_DIR, "language.v", "err.v", & answer,
  340.                       "123", TIMEOUT, RETRY);
  341.  
  342.         if (MV_Result ( ) == MV_SUCCESS)
  343.         {
  344.           switch (answer)
  345.           {
  346.             case '1' : language = MVU_French;  break;
  347.             case '2' : language = MVU_English; break;
  348.             case '3' : language = MVU_Spanish; break;
  349.           }
  350.  
  351.           MVU_GetDateTime (date);
  352.  
  353.           date_field = MVU_WDAY | MVU_MDAY | MVU_HOUR | MVU_MIN;
  354.           MVU_PlayDate (PROMPT_DIR, date, date_field,
  355.                            MV_NoAbortOnDtmf, language);
  356.           MV_Play ("goodbye.v", MV_AbortOnDtmf);
  357.         }
  358.       }
  359.  
  360.       MV_OnHook ( );
  361.     }
  362.  
  363.     MV_StopLH ( );
  364.   }
  365.  
  366.  
  367.   void main (void)
  368.   {
  369.     MV_AllLineHandlers = LineHandler;
  370.  
  371.     if (MV_Start ( ) == MV_SUCCESS)
  372.     {
  373.       MV_WaitEscape ( );    /* Waits until the ESCAPE key is pressed */
  374.       MV_Stop ( );
  375.     }
  376.     else
  377.       printf ("Initialization error");
  378.   }
  379.  
  380.  Contact us for a complete list of functions provided. 
  381.  
  382.  All this for only $799 US 
  383.  
  384.  Multi-Fax Version 2.0 
  385.  
  386.  ITI Software introduces MULTI-FAX, the complete set of tools to write 
  387.  multi-line fax applications for any CAS facsimile boards on OS/2. 
  388.  
  389.  Multi-Fax Product Description 
  390.  
  391.  The MULTI-FAX toolkit allows programmers (experienced or not) to write 
  392.  applications which handle fax transmission.  The toolkit can handle up to ten 
  393.  fax boards simultaneously in a single PC. 
  394.  
  395.  MULTI-FAX will send any ASCII files, PCX or DCX graphic files without format 
  396.  conversion.  You can send multiple documents in a single call. 
  397.  
  398.  Used along with ITI Software's MULTI-VOICE toolkit, the MULTI-FAX toolkit 
  399.  allows programmers to create highly sophisticated software to handle all 
  400.  aspects of telephone interfacing.  Applications such as Fax-Mail, Document 
  401.  Broadcasting and Store-And-Forward can be implemented with minimum effort. 
  402.  
  403.  Multi-Fax Example Programs 
  404.  
  405.  Many example programs are provided to show how to call most procedures and 
  406.  functions.  You can modify these programs to suit your own needs. 
  407.  
  408.  System Requirements 
  409.  
  410.  IBM PC or compatible running DOS 3.3 or higher (5.0 recommended) Any CAS 
  411.  compatible Fax Processing board.  C/C++ Compiler:  Borland's V2.0..V4.5, 
  412.  Borland's Turbo V2.0..V3.0 or Microsoft V5.1..V8.0. 
  413.  
  414.  Fax Sending Sample Program 
  415.  
  416.   #include "stdio.h"
  417.   #include "MultiFax.h"
  418.  
  419.   void main (void)
  420.   {
  421.     int fax_handle
  422.  
  423.     /* Start MULTI-FAX and verify if there is a FAX board in the PC */
  424.  
  425.     if (MF_Start () == 0)
  426.     {
  427.       printf ("No board found. \n");
  428.       exit (-1);
  429.     }
  430.  
  431.     /* Create a fax entry. */
  432.     fax_handle = MF_CreateFax ();
  433.  
  434.     /* Add company logo on cover page. */
  435.     MF_AddLogo (fax_handle, "logo.pcx");
  436.  
  437.     /* Add a message to the cover page. */
  438.     MF_AddCoverPageText (fax_handle, "This is the cover page message.");
  439.  
  440.     /* Add ASCII text file "FAX.TXT" and graphic document "FAX.DCX". */
  441.     MF_AddDocument (fax_handle, MF_ASCII_80, "fax.txt", MF_LETTER);
  442.     MF_AddDocument (fax_handle, MF_DCX, "fax.dcx", MF_LETTER);
  443.  
  444.     /* Send it using highest resolution */
  445.     MF_SetResolution (fax_handle, MF_FINE);
  446.  
  447.     MF_SetDestinationName (fax_handle, "Your Name");
  448.     MF_SetSenderName (fax_handle, "ITI Software");
  449.  
  450.     MF_Send (fax_handle, MF_ANY_BOARD, "555-1212");
  451.  
  452.     MF_FreeFax (fax_handle);
  453.   }
  454.  
  455.  Contact us for a complete list of functions provided. 
  456.  
  457.  All this for only $299 US 
  458.  
  459.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  460.  
  461.  Rexx Symposium Dates Announced 
  462.  
  463.  Reserve May 13-15 next year for the Rexx Symposium and meeting of the Rexx 
  464.  Language Association.  We will meet in Austin, Texas, and have negotiated low 
  465.  lodging rates at the Hyatt Regency.  The Call for Speakers and more 
  466.  information will follow. 
  467.  
  468.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  469.  
  470.  OS/2 Electronic Magazines 
  471.  
  472.      OS/2 Warp Weekly - 
  473.       gopher://os2info.austin.ibm.com/11/nl/os2news/os2news.70. 
  474.  
  475.      OS/2 Warp Monthly - http://www.austin.ibm.com/pspinfo/newsletters.html 
  476.  
  477.      IBM NetNews Magazine - http://www.ibm.com/mag/netnews/ 
  478.  
  479.      OS/2 Warp Flash Magazine - 
  480.       http://www.iceonline.com/home/duncans/warpflash.html 
  481.  
  482.      OS/2 Developer Magazine - http://www.mfi.com/os2dev/os2maginf.html 
  483.  
  484.      OS/2 Connect Magazine - 
  485.       http://warp.eecs.berkeley.edu/os2/warppage/connect/toc.html 
  486.  
  487.      Inside OS/2 Magazine - http://www.cobb.ziff.com/~cobb/os2/ 
  488.  
  489.      IBM Personal Software Magazine - 
  490.       http://www.austin.ibm.com/pspinfo/pcugpsm.html 
  491.  
  492.      IBM Personal Systems Magazine - http://pscc.dfw.ibm.com/psmag/index.html 
  493.  
  494.      IBM Software Quarterly Magazine - http://pscc.dfw.ibm.com/sq/enter.htm 
  495.  
  496.  [Editor's note - We still get no respect.  Sigh.] 
  497.  
  498.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  499.  
  500.  New GNU Fortran Available 
  501.  
  502.  The new version of GNU Fortran (g77-0.5.16) has been ported to emx. 
  503.  
  504.  It's available for anonymous ftp on: 
  505.  
  506.      ftp.uni-stuttgart.de - /pub/systems/os2/emx0.9a/contrib 
  507.      ftp.leo.org - /pub/comp/os/os2/gnu/emx+gcc/contrib 
  508.      ftp.cdrom.com - /pub/os2/incoming 
  509.      hobbes.nmsu.edu - /incoming 
  510.  
  511.  Look for g77bin.zip (binaries) and g77src.zip (source). 
  512.  
  513.  This port of g77 uses now the backend of gcc-2.7.0.  The executables 
  514.  (g77bin.zip) should work with gcc-2.6.3 binaries, too. 
  515.  
  516.  Please send bug reports for g77 to fortran@gnu.ai.mit.edu, except for bugs 
  517.  introduced by the port, which should be reported to me.  If you are not sure, 
  518.  send bugs to me. 
  519.  
  520.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  521.  
  522.   Contact: Dick Goran
  523.   C F S Nevada, Inc.
  524.   Voice:  1-800-864-2358, 1-702-732-9616
  525.   FAX:  1-702-732-3847
  526.   Internet:  dgoran@cfsrexx.com
  527.   CompuServe:  71154,2002
  528.  
  529.  Free OS/2 Related Drawings on the Internet 
  530.  
  531.  Las Vegas, Nevada (9/28/95) -- Beginning on October 1, 1995 C F S Nevada, Inc. 
  532.  will offer free monthly drawings at its Internet World Wide Web site 
  533.  <http://www.cfsrexx.com>.  The winners of the monthly drawings will each be 
  534.  entitled to receive a complimentary copy of C F S Nevada, Inc.'s 
  535.  award-winning, best selling REXX Reference Summary Handbook by Dick Goran or a 
  536.  complimentary key to enable its new MKWINOS/2 program product.  MKWINOS/2 
  537.  creates OS/2 Desktop objects that are equivalent to your Windows Program 
  538.  Manager and its contents.  Full details about both the REXX Reference Summary 
  539.  Handbook and MKWINOS/2 will be found on C F S Nevada, Inc.'s WWW site. 
  540.  
  541.  Though not the first WWW giveaway, this drawing is one of the few that will 
  542.  offer entrants a chance each month to win multiple awards.  The rules 
  543.  governing the drawing are listed on C F S Nevada, Inc.'s home page. 
  544.  
  545.  The only hardware requirement necessary to complete an entry form for the 
  546.  drawing is a WWW browser that supports form submission.  It is not necessary 
  547.  that the entrant be running OS/2. 
  548.  
  549.  C F S Nevada, Inc.  is a Las Vegas based producer and publisher of OS/2 
  550.  related software and publications as well providing commercial OS/2 training. 
  551.  Links on their WWW site are provided for OS/2 related hardware and software as 
  552.  well as some unusual, non-computer related sites. 
  553.  
  554.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  555.  
  556.  Bubble Hint Custom Control for OS/2 PM 
  557.  
  558.  For more information:  http://www.secant.com or info@secant.com 
  559.  
  560.  Now you can add bubble hints to any OS/2 program with our new Hint Bubble 
  561.  Custom Control.  You can attach them to any control, such as those confusing 
  562.  toolbar buttons, and they will pop up after a specified time period to provide 
  563.  addtional information.  This control is provided with a "C" interface only, 
  564.  although it may come out in the next release of the ObjectPM Control Pack with 
  565.  all the wrapper classes.  Everything you need is included -- header files, 
  566.  libraries and DLL's.  This is a "teaser" to drum up interest in our custom 
  567.  control package and OS/2 custom controls in general. 
  568.  
  569.  No source provided, but may be distributed with any executable royalty-free. 
  570.  
  571.  Come and get it from our Web page at http://www.secant.com.  Please do not 
  572.  post on any other ftp site, as we would like to monitor interest by counting 
  573.  ftp'd copies. 
  574.  
  575.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  576.  
  577.  Stardock's Object Desktop is Here 
  578.  
  579.  Stardock Systems will begin shipping its Object Desktop on October 2, 1995. 
  580.  Targeting both the corporate and retail markets, Object Desktop is an advanced 
  581.  desktop environment that "turbo-charges" OS/2, improving performance, 
  582.  flexibility, and ease of use. 
  583.  
  584.  Object Desktop enhances the existing OS/2 environment with updated icons, 
  585.  frame controls, and command buttons, and adds new tools designed to boost 
  586.  productivity and system performance.  The new features include the Object 
  587.  Navigator, Control Center, Keyboard LaunchPad, Object Archives, and HyperDrive 
  588.  and HyperCache features. 
  589.  
  590.  "I haven't been this excited about a product since OS/2 Warp itself."  said 
  591.  David Barnes, Senior Marketing Manager at IBM Personal Software Products.  "My 
  592.  competitors recently released a product that has some nice features.  But 
  593.  Object Desktop gave me everything they have and a lot more (and on a more 
  594.  solid foundation--OS/2 Warp).  Object Desktop will be the first thing I 
  595.  install on any of my systems from now on." 
  596.  
  597.  Object Desktop carries a suggested retail price of $99.95.  Stardock expects 
  598.  the typical street price to be significantly less than that.  Site licensing 
  599.  and wholesale pricing sheets can be obtained from Stardock at 313-453-0328 
  600.  (fax 313/453-1480). 
  601.  
  602.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  603.  
  604.  I've put together a new version of my screen saver "Blackout."  The program is 
  605.  intended for DPMS, or "Green" monitors which can be shut off automatically by 
  606.  using this program; this is accomplished by turning off the syncronization 
  607.  pulses to the monitor.  The screen saver has three modes of saving:  1) it 
  608.  reduces colour intensity on screen, and 2) it sets the monitor in suspend 
  609.  mode, and 3) it switches the monitor off.  No fancy graphics, but it does the 
  610.  job - saves the screen. 
  611.  
  612.  The program is free and is distributed with source code.  I have put version 
  613.  0.94 to hobbes today, so it can probably be found in the incoming or new 
  614.  directory.  The archive name is "black094.zip". 
  615.  
  616.  The program requires the emx runtime library, which is also available from 
  617.  hobbes or ftp-os2.cdrom.com (/pub/os2/unix/emx09a/emxrt.zip). 
  618.  
  619.  Changes from version 0.93: 
  620.  
  621.      Timer implementation changed to work with pre-Warp OS/2. 
  622.  
  623.      Mouse move sensing code changed slightly to overcome the problem with 
  624.       spurious mousemove events.  Result is that the -m switch works more 
  625.       reliably together with Filebar and some other programs that caused 
  626.       problems before. 
  627.  
  628.      The switch -p was added (compatibility with some more monitors/graphics 
  629.       adapters). 
  630.  
  631.      The switch -n was added (to use Blackout as a minimalistc screen saver 
  632.       for non-DPMS systems). 
  633.  
  634.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  635.  
  636.  IBM announces OS/2 Warp Entertainment Toolkit beta 
  637.  
  638.  Kit for games, entertainment software developers 
  639.  
  640.  AUSTIN, Texas, Oct.  3, 1995...IBM today announced the availability of the 
  641.  beta version of the OS/2* Warp Entertainment Toolkit on "The Developer 
  642.  Connection for OS/2, Volume 8" (DevCon8).  The beta has been distributed to 
  643.  the more than 17,000 developers who are members of the Developers Assistance 
  644.  Program (DAP). 
  645.  
  646.  The Toolkit offers new video, audio, joystick, and networking enhancements 
  647.  from IBM that can help developers create exciting PC entertainment titles for 
  648.  IBM's OS/2 Warp and build on the existing resources in DevCon.  DAP members 
  649.  receive tools, software technology, and information quarterly on the DevCon 
  650.  CD-ROM for use in OS/2 Warp development efforts. 
  651.  
  652.  "Developers want direct access to devices and cross-platform capabilities," 
  653.  said Lloyd Webber, IBM Personal Software Products worldwide games brand 
  654.  manager.  "The OS/2 Warp Entertainment Toolkit gives them those resources for 
  655.  developing sophisticated interactive PC entertainment for the OS/2 market." 
  656.  
  657.  New development tools 
  658.  
  659.  The Entertainment Toolkit offers the following capability improvements in 
  660.  areas ranging from sound and imagery to player interaction: 
  661.  
  662.      OS/2 Warp Video offers enhanced software support to OS/2 digital video 
  663.       and PC entertainment programs through features like Direct Interface 
  664.       Video Extensions (DIVE) with full-screen support, Direct Access to Video 
  665.       Buffer and 32-bit Virtual I/O.  DIVE, an API in OS/2 Warp, gives OS/2 
  666.       applications direct access to PC video hardware, enabling developers to 
  667.       generate the high-speed graphics needed for today's advanced multimedia 
  668.       software.  The DIVE graphics interface allows powerful, high-speed games 
  669.       and digital video applications to use a single high-speed API for such 
  670.       useful techniques as stretching (manipulating an image to fit any screen 
  671.       size), clipping ( reusing a graphic in different areas of an application) 
  672.       and color conversion (dictating the color palates used in the 
  673.       application). 
  674.  
  675.      OS/2 Warp 3D enables 3D graphics modeling and rendering to ensure maximum 
  676.       visual performance.  IBM integrates the BRender Power Rendering System, a 
  677.       real-time, 3D graphics software by Argonaut Technologies Ltd., to meet 
  678.       the speed, size, scalability, flexibility and power requirements of the 
  679.       most demanding 3D designers. 
  680.  
  681.      OS/2 Warp Audio features a direct audio interface that provides a 
  682.       high-speed audio alternative for applications, such as games, that cannot 
  683.       afford the more complex methods of synchronizing sound effects with 
  684.       actions. IBM also provides a musical instrument digital interface (MIDI) 
  685.       subsystem that produces the advantage of real-time processing of musical 
  686.       data within the driver itself. 
  687.  
  688.      OS/2 Warp Input offers a standard interface for OS/2 PC entertainment 
  689.       programmers who want to utilize a joystick with their products.  OS/2 
  690.       Warp Input also eliminates the joystick response "flicker" effect seen in 
  691.       many DOS games running under OS/2. 
  692.  
  693.      OS/2 Warp Multiplayer Networking allows developers to write code that 
  694.       permits multiple players to play together and allows additional players 
  695.       to join the game in progress.  The host computer will ensure that the 
  696.       visiting player's client is immediately updated with the game's status. 
  697.       Plus, all clients are informed of the presence of the new player across 
  698.       the network. 
  699.  
  700.  Additional ISV support 
  701.  
  702.  Developers can access the OS/2 Warp gaming page at 
  703.  (http://www.austin.ibm.com/os2games) to receive tools, information and DevCon 
  704.  updates.  Developers also can use the home page to provide feedback and sign 
  705.  up for free membership in DAP, which provides technical support and assistance 
  706.  to developers working with OS/2. 
  707.  
  708.  The OS/2 Warp Entertainment Toolkit is expected to be complete in the first 
  709.  quarter of 1996.  The entire Toolkit will be available on DevCon and pieces of 
  710.  it will be available on the OS/2 Warp games home page. 
  711.  
  712.  To assist OS/2 developers, IBM also sponsors Solution Partnership Centers 
  713.  located in San Mateo, Calif.  and Waltham, Mass.  ISVs using the centers have 
  714.  access to PC hardware and interaction with other software developers, and 
  715.  receive technical support throughout the development process in a lab 
  716.  environment. 
  717.  
  718.  Solution developer support of OS/2 Warp is growing.  In 1995, 70 software 
  719.  developers have announced development plans for more than 200 new native OS/2 
  720.  Warp applications on both Intel and PowerPC platforms, in addition to the 
  721.  existing 2,500 OS/2 applications currently on the market.  Nearly 3 million 
  722.  copies of OS/2 Warp have been sold since it was launched. 
  723.  
  724.  IBM news releases are available on the Internet, via the IBM Home Page at 
  725.  http://www.ibm.com 
  726.  
  727.  The IBM Fax Information Service allows you to receive facsimiles of prior IBM 
  728.  product press releases.  Dial 1-800-IBM-4FAX and enter "99" at the voice menu. 
  729.  
  730.  * Indicates trademark or registered trademark of the IBM Corp. 
  731.  
  732.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  733.  
  734.  IBM Pioneers Groupware For Developers 
  735.  
  736.  Cutting-edge object repository and software configuration management services 
  737.  couple to deliver an industry first 
  738.  
  739.  SAN JOSE, CA, October 10, 1995 ...  Application development teams are getting 
  740.  connected through a powerful new tool from IBM, TeamConnection*. Combining the 
  741.  industry's most robust object repository and advanced software configuration 
  742.  management services, TeamConnection provides a LAN-based client/server 
  743.  development environment that allows teams to collaborate during each step of 
  744.  the development cycle. 
  745.  
  746.  TeamConnection provides an unprecedented range of capabilities, including 
  747.  software configuration, version control, and problem tracking, to manage team 
  748.  development through the entire application development life cycle.  From 
  749.  business modeling and application design through building, deploying and 
  750.  maintaining an application, developers can share data, objects, and code in a 
  751.  collaborative work environment. 
  752.  
  753.  Ciba-Geigy Ltd., a biological and chemical company with 80,000 employees 
  754.  worldwide, is among a number of companies that have evaluated TeamConnection. 
  755.  "TeamConnection will bring a whole new dimension to our application 
  756.  development efforts," said Patrick Deville, new technologies consultant, 
  757.  Ciba-Geigy Limited.  "It provides our LAN-based development team with the 
  758.  robust management and library functions that we expect from our mainframe 
  759.  systems.  We are able to eliminate many manual steps through the managed team 
  760.  development environment provided by TeamConnection, increasing our developer 
  761.  productivity and maximizing the quality of our applications." 
  762.  
  763.  TeamConnection is built on Object Design, Inc.'s ObjectStore** object-oriented 
  764.  database, which allows the TeamConnection repository to store, with high 
  765.  performance, both coarse and fine-grained objects, such as data elements and 
  766.  logic records.  ObjectStore supports the information model through which 
  767.  various development tools can share data and work together to rapidly build 
  768.  and improve applications. 
  769.  
  770.  "TeamConnection creates a collaborative development environment on the LAN," 
  771.  said Tim Negris, vice president, sales and marketing, IBM Software Solutions. 
  772.  "It allows teams to store development objects in the repository on the server 
  773.  and access and use that information on their client workstations. The ability 
  774.  to share and reuse development objects significantly boosts productivity and 
  775.  software quality." 
  776.  
  777.  Mr.  Negris added that IBM plans to aggressively seek participation from 
  778.  independent software vendors (ISVs).  "With open object interfaces, 
  779.  TeamConnection is an ideal repository for storing other vendors' tool data," 
  780.  he said. 
  781.  
  782.  According to Judith Hurwitz, president and CEO of Hurwitz Consulting Group 
  783.  Inc., TeamConnection represents an important component in effective team 
  784.  software development.  "Choosing a visual development environment is only half 
  785.  of the solution," said Hurwitz.  "You need a deployment strategy for 
  786.  client/server."  TeamConnection server and client functions are available on 
  787.  OS/2*.  Server functions will be extended to AIX* and other UNIX** platforms, 
  788.  and Windows NT**.  Client support will be extended to AIX and other UNIX 
  789.  platforms, and the Windows** family.  In addition, build support is provided 
  790.  for OS/2 and MVS*, and will be extended to include AIX and other UNIX 
  791.  platforms, VSE*, OS/400*, and the Windows family. 
  792.  
  793.  A number of cross-platform application development tools from IBM are 
  794.  integrated with TeamConnection, including:  VisualGen* V2.0, a client/server 
  795.  visual application generation tool; VisualAge for C++*, an award-winning 
  796.  visual development environment for C++; VisualSet for OS/2 COBOL*, a visual, 
  797.  object-oriented desktop version of COBOL; and PL/I for OS/2*, a desktop 
  798.  PL/I-based development environment that features a graphical user interface 
  799.  builder.  IBM plans to further enhance the integration of tools to 
  800.  TeamConnection as new releases of current offerings and new tools become 
  801.  available. 
  802.  
  803.  TeamConnection's set of open Application Programming Interfaces (APIs) 
  804.  supports the integration of non-IBM tools into the team development 
  805.  environment, allowing customers to leverage their existing investments. 
  806.  Today's announcement includes a new ISV program to aggressively jump-start 
  807.  TeamConnection integration. 
  808.  
  809.  Independent Software Vendor Program 
  810.  
  811.  TeamConnection can provide a set of services to ISV tools, which will extend 
  812.  tool capabilities in areas that are key to managing the application 
  813.  development life cycle.  The first of many vendors with leadership technology 
  814.  expected to incorporate TeamConnection services is Compagnie Generale 
  815.  d'Informatique (CGI), a worldwide provider of application development software 
  816.  and services.  CGI has integrated PACBASE/CS**, its life-cycle development 
  817.  environment, with TeamConnection to take advantage of advanced software 
  818.  configuration management functions. 
  819.  
  820.  Vendors interested in extending the value of their tools through integration 
  821.  with TeamConnection can participate in IBM's vendor enablement program.  This 
  822.  program provides integration assistance to qualified tool vendors. 
  823.  
  824.  TeamConnection's Advanced Features 
  825.  
  826.      Configuration management support to help identify, organize, manage and 
  827.       control access to development data.  In addition, team members are 
  828.       notified of changes to development data and alerted when action on their 
  829.       part is required; 
  830.  
  831.      Version control features, which minimize storage requirements and 
  832.       preserve application versions at critical points in the development 
  833.       process so that programmers can make modifications while working with a 
  834.       functioning version of their code; 
  835.  
  836.      Integrated build functionality lets teams split development into multiple 
  837.       parallel tasks, increasing efficiency.  Developers can create 
  838.       applications on one server and have machine-specific versions 
  839.       automatically built for other processor types across a LAN, dramatically 
  840.       increasing their productivity; 
  841.  
  842.      Packaging and distribution support handles electronic application 
  843.       distribution across LANs via file server technology such as IBM's NetView 
  844.       Distribution Manager/2*; 
  845.  
  846.      Problem tracking and change control support manages the process of 
  847.       changing development data, keeping track of what changed, who changed it 
  848.       and why it was changed -- and associates defects and features with 
  849.       appropriate changes; 
  850.  
  851.      Reporting facility provides the ability to query data and project status; 
  852.  
  853.      A backup and recovery facility handles archival storage, and; 
  854.  
  855.      Information model provides the integrating platform through which 
  856.       development tools share data. 
  857.  
  858.  TeamConnection for OS/2 Pricing and Availability 
  859.  
  860.  TeamConnection for OS/2 is priced at $1999 per user and is available October 
  861.  24, 1995.  For additional information on TeamConnection for OS/2 or the vendor 
  862.  enablement program, please call 1-800-IBM-3333. 
  863.  
  864.  For information via the Internet, users can access the IBM software page at 
  865.  http://www.software.ibm.com.  Then, search on "go TeamConnection." IBM's home 
  866.  page can be found at http://www.ibm.com. 
  867.  
  868.  IBM, the world's largest software provider, creates, develops and manufactures 
  869.  the industry's most advanced information technologies, including computer 
  870.  systems, software, networking systems, storage devices and microelectronics. 
  871.  IBM's Software Solutions Division provides data management, application 
  872.  development and workgroup solutions for mission-critical applications on PCs, 
  873.  workstations, LANs and host systems. 
  874.  
  875.  * Indicates trademark or registered trademark of International Business 
  876.  Machines Corporation 
  877.  
  878.  ** Products or companies mentioned are trademarks or registered trademarks of 
  879.  their respective holder. 
  880.  
  881.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  882.  
  883.  VisualAge For COBOL For OS/2 Extends COBOL To Your OS/2 Workstation 
  884.  
  885.  IBM VisualAge for COBOL for OS/2 revitalizes your COBOL applications by 
  886.  extending COBOL to your OS/2 workstation 
  887.  
  888.  In addition to bringing COBOL to your OS/2 desktop, IBM VisualAge for COBOL 
  889.  for OS/2: 
  890.  
  891.      Offers object-oriented language extensions. 
  892.  
  893.      Extends COBOL to a client/server environment. 
  894.  
  895.      Increases programmer productivity. 
  896.  
  897.      Saves you time and money by taking advantage of the current skill base in 
  898.       your organization and preserving your current data. 
  899.  
  900.      Increases ease-of-use with a variety of development tools. 
  901.  
  902.  IBM VisualAge for COBOL for OS/2 is a cost-effective solution that offers the 
  903.  following enhancements to COBOL. 
  904.  
  905.      Object-Oriented Language Extensions: 
  906.  
  907.         -  Allow COBOL programmers to create objects in a language they already 
  908.            know, eliminating a long learning curve. 
  909.         -  Offer 32-bit implementation. 
  910.         -  Provide direct-to-SOM implementation. 
  911.  
  912.      Client/Server Enablers: 
  913.  
  914.         -  Run COBOL programs on your OS/2 desktop, while your data remains on 
  915.            the host. 
  916.         -  Easily access remote data from DB2, CICS, VSAM/SAM MVS files, and 
  917.            OS/400 Record Files. 
  918.         -  Work with MQSeries for OS/2 using MQSeries Three Tier for OS/2. 
  919.         -  Comply with ISO and ANSI COBOL standards. 
  920.  
  921.      Improved Productivity and Ease-of-Use: 
  922.  
  923.         -  Easily take advantage of these COBOL enhancements with the help of a 
  924.            rich set of tools. 
  925.  
  926.  IBM VisualAge for COBOL for OS/2 is slated to become available in early 
  927.  November. 
  928.  
  929.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  930.  
  931.  Mr. Ed Now Available 
  932.  
  933.  Mr.Ed is a multi-window 32-bit shareware text editor for OS/2 PM.  Mr.Ed's 
  934.  functionality is designed to be suitable for any text editing job. 
  935.  
  936.  In addition, Mr.Ed provides several features that support writing source code. 
  937.  Mr.Ed also takes advantage of OS/2 specialities:  Drag'n'Drop (files, fonts, 
  938.  colors), EAs (cursor position, bookmarks), multiple threads, and clipboard 
  939.  data exchange. 
  940.  
  941.  Furthermore, Mr.Ed is not based on the standard MLE control element, so there 
  942.  is no loss of performance when editing large files. 
  943.  
  944.  Featues: 
  945.  
  946.      configurable Syntax-Highlighting 
  947.      configurable third-party Online-Help 
  948.      configurable context menu 
  949.      unlimited number of edit windows 
  950.      "Window Monitor" 
  951.      pipe-operator support 
  952.      configuration via commandline 
  953.      cursor is set to his former editing position when a file is opened 
  954.      Drag & Drop support 
  955.      easy to use macro recorder 
  956.      list of C/C++ functions defined in a source file 
  957.      jumps to free defineable brackets 
  958.      persistant bookmarks 
  959.      line sorting 
  960.      free defineable keyboard shortcuts 
  961.      various word functions 
  962.      configurable print function 
  963.      word wrap function 
  964.      automatic recognition of unix-format files 
  965.      configurable toolbar 
  966.      and much more... 
  967.  
  968.  Mr.Ed is shareware, but fully functional and not "crippled" in any way. 
  969.  
  970.  The archive can be downloaded from the following sites: 
  971.  
  972.  hobbes.cdrom.com (currently in incoming, proposed directory: /pub/os2/editors) 
  973.  
  974.  ftp-os2.nmsu.edu (currently in incoming, proposed directory: /pub/os2/editors) 
  975.  
  976.  Filename:  mred103e.zip (English version), mred103g.zip (German version) 
  977.  
  978.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  979.  
  980.  Freeware OS/2 Class Library 1.11 Now Available 
  981.  
  982.  The new release 1.11 of our freeware OS/2 Class Library (OCL) for OS/2 VIO and 
  983.  OS/2 PM is now available via CIS (GO OS2INSIDE) and ftp (Hobbes and 
  984.  ftp.leo.org). 
  985.  
  986.  Don't panic!  These are really good news for C++ programmers using IBM C-Set++ 
  987.  2.x, VisualAge C++ 3.0, Borland C++ 2.0, Metaware HighC/C++ 3.3x, Watcom C++ 
  988.  10.x and - guess it - gcc/emx 2.7.0! 
  989.  
  990.  Yes - the port for gcc/emx is done and working.  Thanx to Ralph Paul who did 
  991.  the job. 
  992.  
  993.  There is another major step foreward in OCL 1.11:  The notebook bug - annoying 
  994.  since the first release - has been fixed. 
  995.  
  996.  The class OProcStat for complete system reports is now available for all 
  997.  supported compilers when developing for OS/2 Warp.  The library now uses the 
  998.  new 32bit-API DosQuerySysState.  So no thunking is required and OProcStat can 
  999.  be used with Borland, Metaware and gcc/emx as well. 
  1000.  
  1001.  The reference book has been updated, but it's far from complete.  We're 
  1002.  working on this topic. 
  1003.  
  1004.  Hi, gcc-users - give it a try!  Please report everything, success or problems, 
  1005.  to the mail address printed in the OCL Reference Book. 
  1006.  
  1007.  You need the following archives: 
  1008.  
  1009.      OCLINST.ZIP - Installation and Maintenance Utility Pack 
  1010.      OCL111.ZIP - OCL 1.11 Release Pack 
  1011.  
  1012.  Users of OCL 1.10 can use the Installation and Maintenance Tools shipped with 
  1013.  this release. 
  1014.  
  1015.  Announcements - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  1016.  
  1017.  
  1018. ΓòÉΓòÉΓòÉ 5. How Do I Get EDM/2? ΓòÉΓòÉΓòÉ
  1019.  
  1020. How Do I Get EDM/2? 
  1021.  
  1022. EDM/2 can be obtained in any of the following ways: 
  1023.  
  1024. On the Internet 
  1025.  
  1026.      All back issues are available via anonymous FTP from the following sites: 
  1027.  
  1028.         -  hobbes.nmsu.edu in the /os2/newsltr directory. 
  1029.         -  ftp.luth.se in the /pub/os2/programming/newsletter directory. 
  1030.         -  generalhq.pc.cc.cmu.edu in the /pub/newsletters/edm2 directory. 
  1031.  
  1032.      The EDM/2 mailing list.  Send an empty message to edm2-info@knex.mind.org 
  1033.       to receive a file containing (among other things) instructions for 
  1034.       subscribing to EDM/2.  This is a UUCP connection, so be patient please. 
  1035.  
  1036.      IBM's external gopher/WWW server in Almaden. The address is 
  1037.       index.almaden.ibm.com and it is in the "Non-IBM-Originated" submenu of 
  1038.       the "OS/2 Information" menu; the URL is 
  1039.       "gopher://index.almaden.ibm.com/1nonibm/os2nonib.70". 
  1040.  
  1041.  On Compuserve 
  1042.  
  1043.  All back issues are available in the OS/2 Developers Forum 2. 
  1044.  
  1045.  IBM Internal 
  1046.  
  1047.      IBM's internal gopher/WWW server in Almaden. The address is 
  1048.       n6tfx.almaden.ibm.com and it is in the "Non-IBM-Originated Files" menu; 
  1049.       the URL is "gopher://n6tfx.almaden.ibm.com/1!!nonibm/nonibm.70". 
  1050.  
  1051.  On BBS's 
  1052.  
  1053.      From BBS's in Denmark, send email to Jesper Nielsen at 
  1054.       afdata@pop02.ny.us.ibm.net for a location near you. 
  1055.  
  1056.  How do I Get EDM/2? - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  1057.  
  1058.  
  1059. ΓòÉΓòÉΓòÉ 6. Building an Editor (Part 3) ΓòÉΓòÉΓòÉ
  1060.  
  1061. Building an Editor (Part 3) 
  1062.  
  1063. Written by Eric Slaats and Marc Mittelmeijer 
  1064.  
  1065. Introduction 
  1066.  
  1067. In the last two articles in this series we created a small editor based on the 
  1068. MLE control.  We didn't receive as much mail as the previous article, however. 
  1069. (Maybe because the mail server we are attached to crashed?)  So if you sent 
  1070. mail to us and didn't receive a reply, please send it again.  Some of the mail 
  1071. we received (thanks for the kudo's) mentioned some items worth repeating here. 
  1072.  
  1073. Memory allocated? 
  1074.  
  1075. We received some mail from people who had problems recompiling the samples 
  1076. because the new and delete statements are used.  Two things have to be said 
  1077. about this. 
  1078.  
  1079.      new and delete are C++ functions, so in order to use them, you've got to 
  1080.       use a C++ compiler.  If a straight C compiler is used, these statements 
  1081.       are not recognized.  If you don't want to use these statements, malloc 
  1082.       and free or the OS/2 API calls DosAllocMem and DosFreeMem may be used. 
  1083.       All these methods should provide you with the amount of memory requested. 
  1084.  
  1085.      The second item is a bug in the way memory is allocated in the EDITOR2 
  1086.       example.  It was Graham TerMarsch who brought this to our attention.  If 
  1087.       memory is allocated by using new[], it should be freed by using delete[]. 
  1088.       This isn't fatal,the program will compile and work just fine.  On the 
  1089.       other hand it may cause some erratic behavior.  Besides that if only the 
  1090.       pointer is freed, the allocated memory will not be freed!  In the 
  1091.       examples included with this article, this bug is corrected.  (Thanks 
  1092.       Graham.) 
  1093.  
  1094.  Problems with the resource file! 
  1095.  
  1096.  Some people who tried to recompile the included resource file with RC or other 
  1097.  compilers then the Borland resource compiler got errors.  The cause for this 
  1098.  is that the Borland compiler doesn't need the os2.h include in the resource 
  1099.  file.  It just assumes it is there.  If the line 
  1100.  
  1101.   #include <os2.h>
  1102.  
  1103.  is added, the resource file will compile just fine. 
  1104.  
  1105.  In this article we will cover how to change the fonts used by the MLE editor, 
  1106.  and a way to save a standard font for the editor.  To save font information, 
  1107.  we will use a .INI file. 
  1108.  
  1109.  The button icons are somewhat smaller in the EDITOR3 example.  We use a 
  1110.  1280/1024 screen, so the 32x32 buttons don't look obnoxiously large.  Included 
  1111.  in the EDITOR3.ZIP file you'll find a set of 28x28 bitmaps for the buttons. 
  1112.  
  1113.  Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  1114.  
  1115.  
  1116. ΓòÉΓòÉΓòÉ 6.1. Some Strategy ΓòÉΓòÉΓòÉ
  1117.  
  1118.  Some Strategy 
  1119.  
  1120. As mentioned in earlier articles, we think every developer should go the extra 
  1121. mile to fully implement drag and drop.  Of course this also implied fonts. 
  1122. Unfortunately, the MLE control has a few caveats when it comes to handling 
  1123. presentation parameters.  We will look at a way around them. 
  1124.  
  1125. What strategy should we take?  When it comes to fonts there are an awful lot of 
  1126. arguments to consider.  You only have to look at the FONTMETRICS structure (or 
  1127. the derived FATTRS structure) to get our point.  The questions are:  do we need 
  1128. all this information to change the font in the MLE editor?  And what 
  1129. information do we need to save the currently used font? 
  1130.  
  1131. One way to change a font in an MLE control is using drag-n-drop.  If a font 
  1132. palette drop is used, something known as a called presentation parameter is 
  1133. used to change the font.  A presentation parameter is actually a simple string 
  1134. with a description of the parameter in question.  Handling a presentation 
  1135. parameter string is a lot simpler then messing with the FONTMETRICS (or the 
  1136. FATTRS structure) structure.  For the simple things we want to accomplish, the 
  1137. presentation parameter information is an ideal tool and we'll use that as a 
  1138. starting point. 
  1139.  
  1140. We want to be able to change fonts of the editor in two ways: 
  1141.  
  1142.    1. Dropping a font on the MLE. 
  1143.    2. Using the standard font dialog. 
  1144.  
  1145.  If you tried a font drop with the EDITOR2 example you should have found that 
  1146.  this already worked!  You should also have found that some of the font 
  1147.  attributes aren't displayed properly!  For example, take the outline attribute 
  1148.  on a Times Roman font.  You will find that it won't display this font!  Maybe 
  1149.  you've also noticed that the font isn't saved when you shut the editor down. 
  1150.  Something to fix these things has to be done. 
  1151.  
  1152.  The font in an MLE control can be changed in two separate ways: 
  1153.  
  1154.      A MLM_SETFONT message can be posted to the control.  To do this we need a 
  1155.       FATTRS structure which contains all the necessary font information.  (We 
  1156.       will see more about the FATTRS structure in a moment.) 
  1157.  
  1158.      Or, we can use the WinSetPresParam function and set the presentation 
  1159.       parameters for the control.  (It is this function the PM uses to 
  1160.       associate a presentation parameter with a window.  On other words, this 
  1161.       function is invoked when a font is dropped on the MLE.) 
  1162.  
  1163.      The effect of both methods is the same when looking at the editor 
  1164.       (however, we can only set the font-attributes by using the MLM_SETFONT 
  1165.       message, we can't set them with a drop!) 
  1166.  
  1167.  Note:  Both the methods used for setting the font can be undone by the undo 
  1168.  function supplied by the MLE (MLM_UNDO message). 
  1169.  
  1170.  Inside the MLE control though both methods aren't completely compatible. If 
  1171.  the font is set by using a presentation parameter drop, the MLE will process 
  1172.  this drop.  If we query the font in use by an MLE after a font drop - using 
  1173.  the MLM_QUERYFONT message - the FATTRS structure returned by the query will 
  1174.  contain the correct values.  So the MLE processes a font-drop in such a way 
  1175.  that the dropped font can be queried by MLM_QUERYFONT! 
  1176.  
  1177.  On the other hand if we query the font presentation parameter 
  1178.  (WinQueryPresParam with the presentation parameter PP_FONTNAMESIZE), we get 
  1179.  none or the last font dropped.  So the presentation parameter attached to the 
  1180.  control doesn't have to stand for the same font as the control is displaying! 
  1181.  So we should always query the MLE if we want to know what font is in use! 
  1182.  (This may give some trouble if we want to know the point size of a font which 
  1183.  is very easily obtained from a presentation parameter but it's almost 
  1184.  impossible to extract this from a FATTRS structure.) 
  1185.  
  1186.  So what do we need? 
  1187.  
  1188.      A way to capture the font-drop event so the presentation parameter can be 
  1189.       intercepted to fix the attribute problem. 
  1190.  
  1191.      A way to convert the attributes contained in the font presentation 
  1192.       parameter to a FATTRS structure member. 
  1193.  
  1194.      A way to remember the point size of the font in use. 
  1195.  
  1196.  If we've got this, we can build a program which will always show the correct 
  1197.  font, no matter if a presentation parameter is used, or MLM_xxxxxFONT message 
  1198.  is used. 
  1199.  
  1200.  Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  1201.  
  1202.  
  1203. ΓòÉΓòÉΓòÉ 6.2. The Standard Font Dialog ΓòÉΓòÉΓòÉ
  1204.  
  1205.  The Standard Font Dialog 
  1206.  
  1207. One of the ways to change the font in the MLE control is to invoke the 
  1208. MLM_SETFONT message.  This message sends a FATTRS structure to the MLE.  This 
  1209. structure describes fonts and must be filled with valid values so the MLE can 
  1210. select the proper font. 
  1211.  
  1212. The easiest way to obtain these font-values (FATTR structure) is by using the 
  1213. standard font dialog.  Just like the standard file dialog, this dialog was 
  1214. included in OS/2 2.0 to prevent programmers from making all sorts of dialogs to 
  1215. change fonts.  And just like the standard file dialog it has a ridiculous 
  1216. number of things to be initialized before it may be used. 
  1217.  
  1218. To use this dialog a FONTDLG structure has to be initialized before invoking 
  1219. the dialog. 
  1220.  
  1221. typedef struct _FONTDLG
  1222.      {
  1223.      ULONG      cbSize;             // Structure size
  1224.      HPS        hpsScreen;          // Screen presentation space
  1225.      HPS        hpsPrinter;         // Printer presentation space
  1226.      PSZ        pszTitle;           // Dialog title string
  1227.      PSZ        pszPreview;         // Font-preview window string
  1228.      PSZ        pszPtSizeList;      // Application-provided point size list
  1229.      PFNWP      pfnDlgProc;         // Custom dialog procedure
  1230.      PSZ        pszFamilyname;      // Family name buffer
  1231.      FIXED      fxPointSize;        // Point size of the font
  1232.      ULONG      fl;                 // FNTS_* flags
  1233.      ULONG      flFlags;            // FNTF_* flags
  1234.      ULONG      flType;             // The selected type bits
  1235.      ULONG      flTypeMask;         // Mask of type bits to use
  1236.      ILONG      flStyle;            // Selected style bits
  1237.      ULONG      flStyleMask;        // Mask of style bits to use
  1238.      LONG       clrFore;            // Font foreground color
  1239.      LONG       clrBack;            // Font background color
  1240.      ULONG      ulUser;             // Application-defined
  1241.      LONG       lReturn;            // Return value
  1242.      LONG       lSRC;               // System return code
  1243.      LONG       lEmHeight;          // Em height
  1244.      LONG       lXHeight;           // X height
  1245.      LONG       lExternalLeading;   // External leading
  1246.      HMODULE    hMod;               // Module for custom dialog resources
  1247.      FATTRS     fAttrs;             // Font-attribute structure
  1248.      SHORT      sNominalPointSize;  // Font point size
  1249.      USHORT     usWeight;           // Font weight
  1250.      USHORT     usWidth;            // Font width
  1251.      SHORT      x;                  // The x-axis dialog position
  1252.      SHORT      y;                  // The y-axis dialog position
  1253.      USHORT     usDlgId;            // Dialog ID
  1254.      USHORT     usFamilyBufLen;     // Buffersize
  1255.      USHORT     usReserved;         // Reserved
  1256.      } FONTDLG;
  1257.  
  1258. It's hell to fill all these values, so we don't want to fill every member off 
  1259. this structure if we don't need to do it.  Before we can use the font dialog, 
  1260. we fill every item with a NULL value; then we fill the members that are 
  1261. essential for the handling of the font dialog. 
  1262.  
  1263. The following members are absolutely necessary to use the font dialog. 
  1264.  
  1265. FontDlg.cbSize         = sizeof(FONTDLG);  // Set cbsize (Mandatory)
  1266. FontDlg.pszFamilyname  = szCurrentFont;    // Buffer for fontname (previously defined)
  1267. FontDlg.usFamilyBufLen = FACESIZE;         // Size fontname buffer
  1268. FontDlg.clrFore        = CLR_NEUTRAL;      // Foreground color for sample
  1269. FontDlg.clrBack        = CLR_DEFAULT;      // Background color for sample
  1270.  
  1271. To show that with only these values we can make a font dialog work, a FONTDLG 
  1272. example is included in the file EDITOR3.ZIP.  FONTDLG.ZIP contains the complete 
  1273. working code for this example. 
  1274.  
  1275. Treating the font dialog this way in an editor isn't rather user friendly. 
  1276. Usually we want the font dialog to display the font currently in use, including 
  1277. the font size and the attributes (underline etc.).  To obtain this information 
  1278. at least one other member of the FONTDLG structure has to be filled.  This is 
  1279. the field containing the FATTRS structure.  This structure contains the most 
  1280. important font information and is also used by the MLE control.  A filled 
  1281. FATTRS structure containing the information about the font currently in use can 
  1282. be retrieved from the MLE using the MLM_QUERYFONT message. 
  1283.  
  1284. It would be nice if this is enough to initialize the font dialog.  Well, it is. 
  1285. We can set the fl field off the FONTDLG structure and the fontdialog will set 
  1286. itself up according to the values contained in the fAttrs field. 
  1287.  
  1288. FontDlg.fl = FNTS_INITFROMFATTRS;                       // Init FontDialog from FATTRS
  1289. WinSendMsg(hwndMLE, MLM_QUERYFONT, &FontDlg.fAttrs, 0L);// Retrieve font values from MLE
  1290.  
  1291. For now we have enough to build the function that can be incorporated in the 
  1292. editor.  Only a few details have to be taken care off.  Before we start we have 
  1293. to set all the values of the FONTDLG structure to NULL.  Besides that we want 
  1294. the values set by the dialog to be remembered so that the next time the dialog 
  1295. is invoked the proper values (e.g.  point size) will show.  We can achieve both 
  1296. by declaring the FONTDLG variable static.  If a variable is declared as a 
  1297. static, its contents will be remembered until the next time the function in 
  1298. which it is declared is called again.  Besides that, static initializes the 
  1299. variable with NULL values. 
  1300.  
  1301. The new function to change the fonts in the MLE editor will look something like 
  1302. this. 
  1303.  
  1304. case IDM_CHANGEFONT:
  1305.       {
  1306.       char  szCurrentFont[FACESIZE];                          // Setup fontname buffer
  1307.       static  FONTDLG  FontDlg;                               // values FILEDLG set to 0
  1308.  
  1309.       FontDlg.cbSize         = sizeof(FONTDLG);               // Set cbsize (Mandatory)
  1310.       FontDlg.fl             = FNTS_INITFROMFATTRS;           // Init from FATTRS
  1311.       FontDlg.usFamilyBufLen = FACESIZE;                      // Size fontname buffer
  1312.       FontDlg.pszFamilyname  = szCurrentFont;                 // Fontname buffer
  1313.       FontDlg.clrFore        = CLR_NEUTRAL;                   // Foreground color for sample
  1314.       FontDlg.clrBack        = CLR_DEFAULT;                   // Background color for sample
  1315.  
  1316.       WinSendMsg(hwndMLE, MLM_QUERYFONT, &FontDlg.fAttrs, 0L);// Retrieve font values
  1317.  
  1318.       WinFontDlg(HWND_DESKTOP, hwnd, &FontDlg);               // Start font dialog
  1319.       if (FontDlg.lReturn == DID_OK)                          // OK pressed ?
  1320.            WinSendMsg(hwndMLE,                                // Activate new font
  1321.                       MLM_SETFONT,
  1322.                       &FontDlg.fAttrs,
  1323.                       NULL);
  1324.       }
  1325. break;
  1326.  
  1327. If we use it the first time, the default font for the MLE will be displayed. 
  1328. Every time the font dialog is invoked, the last font used is displayed, 
  1329. including the attributes and the point size used (remembered in the static 
  1330. FONTDLG structure). 
  1331.  
  1332. Because this is a small and elegant solution, something has to go wrong, and 
  1333. indeed something does.  We want the editor to incorporate every goody OS/2 has 
  1334. to offer, so dropping a font on the MLE window should result in a font change. 
  1335. If we try this it seems to work just fine.  However there are a few situations 
  1336. where things go wrong. 
  1337.  
  1338.    1. If a font without further attributes (underline, outline, strikeout) is 
  1339.       dropped, the MLE takes over the dropped font and it can be queried 
  1340.       correctly. If the font dialog is opened the right font will show; 
  1341.       however, the font size won't be correct.  The dialog will show the last 
  1342.       font size used!  So we have to find a way to restore the correct font 
  1343.       size in the FONTDLG structure which is used for setting up the 
  1344.       fontdialog. 
  1345.  
  1346.       Apparently the WinFontDlg() function cannot determine the point size from 
  1347.       the FATTRS structure (well, neither can we). 
  1348.  
  1349.    2. If a font with attributes is dropped on the MLE the attributes won't 
  1350.       show. It isn't that the MLE control isn't capable of showing these 
  1351.       attributes; it just won't show them if dropped in the form of a 
  1352.       presentation parameter. 
  1353.  
  1354.  So if we want to support complete font dropping, we've got to do something 
  1355.  about this.  To accomplish this we have to capture a font drop. 
  1356.  
  1357.  Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  1358.  
  1359.  
  1360. ΓòÉΓòÉΓòÉ 6.3. Detecting the Font Presentation Parameter ΓòÉΓòÉΓòÉ
  1361.  
  1362.  Detecting the Font Presentation Parameter 
  1363.  
  1364. What's a presentation parameter? 
  1365.  
  1366. A presentation parameter is a character string that represents certain 
  1367. presentation values such as color- and font- values.  These values can be used 
  1368. when displaying a window.  If we drop a font on the titlebar of a window, the 
  1369. titlebar (also a window) will show that font.  The same thing happens with 
  1370. colors. 
  1371.  
  1372. Note:  Although OS/2 supports most of the presentation parameters for the 
  1373. standard controls in most cases, there are some points when things aren't 
  1374. completely supported.  An example of this is the font drop on an MLE.  Another 
  1375. example is a color drop on an MLE.  (A MLE excepts only indexed colors.) Also, 
  1376. not all OS/2 applications support presentation parameters; the application has 
  1377. to be utilized to do so! 
  1378.  
  1379. For this article we are only interested in the PP_FONTNAMESIZE presentation 
  1380. parameter.  The drop of this presentation parameter is what we want to take 
  1381. actions upon.  If this presentation parameter is queried from the MLE, a string 
  1382. is retrieved that looks something like this: 
  1383.  
  1384. pointsize.facename.attr1.attr2.attr3 
  1385.  
  1386. This structure is always used by PP_FONTNAMESIZE to describe a font.  The items 
  1387. in this string are separated by a dot (.).  Only the first two items are 
  1388. mandatory.  So the following examples are valid presentation parameter strings. 
  1389.  
  1390. "8.Helv"
  1391. "18.Courier Bold"
  1392. "24.Times New Roman Bold Italic"
  1393. "12.System Proportional"
  1394.  
  1395. There are five possible attributes a font can have,although only three of them 
  1396. are supported by the standard font dialog and by the FONTDROP dialog. The 
  1397. attributes bold and italic are normally supported by the font style, so they 
  1398. are omitted in the font dialog.  However these attributes can still be used. 
  1399. If we use bold on a already bold font it gets wider.  If we use italic on a 
  1400. already italic font, the font gets italicized more. 
  1401.  
  1402. These are the five possible font attributes: 
  1403.  
  1404.      Italic 
  1405.      Outline 
  1406.      Strikeout 
  1407.      Underscore 
  1408.      Bold 
  1409.  
  1410.  So the following presentation parameter strings are also valid: 
  1411.  
  1412.   "8.Helv.Outline"
  1413.   "18.Courier Bold.Bold"
  1414.   "24.Times New Roman Bold Italic.Italic.Underscore.Bold"
  1415.   "12.System Proportional.Strikeout"
  1416.  
  1417.  Now we know how a presentation parameter looks and what the possible values 
  1418.  are, we've only got to capture a fontdrop to fix the two points mentioned in 
  1419.  the previous section. 
  1420.  
  1421.  Besides that we've learned another thing.  There aren't three but five font 
  1422.  attributes.  The attributes bold and italic can't be accessed through the 
  1423.  standard font dialog or by the font palette.  Let's take a small detour and 
  1424.  find out how we can use these attributes in our MLE editor. 
  1425.  
  1426.  Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  1427.  
  1428.  
  1429. ΓòÉΓòÉΓòÉ 6.4. Applying the Bold and Italic Attributes ΓòÉΓòÉΓòÉ
  1430.  
  1431.  Applying the Bold and Italic Attributes 
  1432.  
  1433. We can set and query the current font in the MLE by using the MLM_SETFONT and 
  1434. MLM_QUERYFONT messages.  By using these messages, we can build two very simple 
  1435. functions that will enable us to change the contents of a MLE to bold or to 
  1436. italic. 
  1437.  
  1438. Before we look into these functions, lets take a look at the fsSelection field 
  1439. of the FATTRS structure.  This field contains the font attributes.  If this 
  1440. field contains a 0, no attributes are attached to the font.  The following 
  1441. values can be or'd together to make a valid entry for fsSelection. 
  1442.  
  1443.      FATTRS_SEL_ITALIC 
  1444.      FATTRS_SEL_UNDERSCORE 
  1445.      FATTRS_SEL_BOLD 
  1446.      FATTRS_SEL_STRIKEOUT 
  1447.      FATTRS_SEL_OUTLINE 
  1448.  
  1449.  We're only interested in the bold and italic attributes because the rest can 
  1450.  be set through a font drop or by invoking the font dialog. 
  1451.  
  1452.  To change the font to bold or italic, two new entries are added to the edit 
  1453.  menu:  bold and italic.  We want these to be toggle entries.  (Yeah yeah we 
  1454.  know a checkmark in the menu should be in place.)  If one of these menu 
  1455.  options is chosen, the font in the MLE must add the attribute if it isn't 
  1456.  there or delete the attribute if it is there.  To accomplish this we'll use 
  1457.  the XOR oparator (^). 
  1458.  
  1459.  The code example to toggle the bold attribute for the current font looks like 
  1460.  this: 
  1461.  
  1462.   case IDM_BOLD:
  1463.         {
  1464.         FATTRS fAttrs;
  1465.         WinSendMsg( hwndMLE, MLM_QUERYFONT, &fAttrs, NULL ); // Query font
  1466.         fAttrs.fsSelection ^= FATTR_SEL_BOLD;                // XOR with bold attribute
  1467.         WinSendMsg( hwndMLE, MLM_SETFONT, &fAttrs, NULL );   // Set font
  1468.         }
  1469.   break;
  1470.  
  1471.  This is the end of the detour.  Let's get back to the article. 
  1472.  
  1473.  Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  1474.  
  1475.  
  1476. ΓòÉΓòÉΓòÉ 6.5. Capturing a Font Drop ΓòÉΓòÉΓòÉ
  1477.  
  1478.  Capturing a Font Drop 
  1479.  
  1480. What happens if a presentation parameter (font, color or scheme) is dropped on 
  1481. a window, and why do we want to capture this event? 
  1482.  
  1483. We want to capture this event for two reasons (as mentioned in the section 
  1484. about the standard font dialog). 
  1485.  
  1486.    1. It is very hard to determine the font's point size from the FATTRS value 
  1487.       as used by the MLE.  If we set a font by using the font dialog, the point 
  1488.       size set can be remembered.  If a font drop occurs, the point size of the 
  1489.       dropped font may differ from the point size remembered in the FONTDLG 
  1490.       structure.  So by the next call of the Font dialog we've got a problem. 
  1491.  
  1492.       However, the point size can easily be derived from a presentation 
  1493.       parameter.  So, we want to extract the point size from the dropped font 
  1494.       presentation parameter and store it in the FONTDLG structure. 
  1495.  
  1496.    2. A font drop with fonts that has attributes attached isn't processed 
  1497.       properly by the MLE.  By capturing a font drop we can check on the 
  1498.       attributes of the dropped font and set them according to the dropped 
  1499.       font. 
  1500.  
  1501.  To build a solution for both problems we need the presentation parameter 
  1502.  string of the dropped font.  Let's see how we can obtain the string that 
  1503.  describes the dropped font. 
  1504.  
  1505.  If a presentation parameter drop is performed, a WM_PRESPARAMCHANGED message 
  1506.  is sent to the window the drop is performed upon.  (This message also occurs 
  1507.  if the presentation parameters are set using the WinSetPresParam function, or 
  1508.  if the presentation paramaters are inherited.) 
  1509.  
  1510.  If this message is send, the first parameter of the WM_PRESPARAMCHANGED 
  1511.  message contains the type of presentation parameter dropped.  There are quite 
  1512.  a lot (29 to be exact) of presentation parameters but in this case we're only 
  1513.  interested in the PP_FONTNAMESIZE attribute (font name and size attribute). 
  1514.  
  1515.  In our case we have to intercept the WM_PRESPARAMCHANGED message in the MLE 
  1516.  window standard procedure.  This means subclassing the MLE window. 
  1517.  Fortunately, we've already done this to process file drops (see EDM/2 3-6)! So 
  1518.  we only have to add another case for WM_PRESPARAMCHANGED. 
  1519.  
  1520.  If a WM_PRESPARAMCHANGED occurs we can query the presentation parameters of a 
  1521.  window by calling the WinQueryPresParam function.  This function enables us to 
  1522.  query a presentation parameter string.  In our case we want to query the 
  1523.  PP_FONTNAMESIZE parameter.  The WinQueryPresParam function is rather complex; 
  1524.  it looks like this: 
  1525.  
  1526.   WinQueryPresParam(hwnd,             // Window handle
  1527.                     idAttrType1,      // Pres param attribute 1
  1528.                     idAttrType2,      // Pres param attribute 2
  1529.                     pidAttrTypeFound, // Attrib ID found
  1530.                     cbAttrValueLen,   // Size of found attribute
  1531.                     pAttrValue,       // Found attribute value
  1532.                     flOptions);       // Flags
  1533.  
  1534.  This function takes two presentation parameter attributes.  It will search for 
  1535.  the second presentation parameter if the first one isn't found.  Since we only 
  1536.  act upon a WM_PRESPARAMCHANGED with the first parameter set to 
  1537.  PP_FONTSIZENAME, we are sure a presentation parameter is present.  This means 
  1538.  we can ignore the second presentation parameter value in this function. 
  1539.  
  1540.  The only other parameter of this function that we can use is the flOptions 
  1541.  parameter.  With the flags in this field we can control the query in such a 
  1542.  way that we don't query the inherited presentation parameter values from 
  1543.  owners, but the value in the queried window (the MLE window in our case).  To 
  1544.  do this we have to fill flOptions with the QPF_NOINHERIT value. 
  1545.  
  1546.  If we capture the presentation parameter string dropped on the MLE, what 
  1547.  actions do we have to take? 
  1548.  
  1549.  Well first we've got to send the WM_PRESPARAMCHNAGED message to the original 
  1550.  MLE window procedure to make sure the presentation parameter is processed so 
  1551.  that the correct font value is attached to the MLE and will appear in the 
  1552.  FATTRS structure if we query the MLE. 
  1553.  
  1554.  The original MLE window procedure is queried at the start of the subclass (see 
  1555.  EDM2-6). 
  1556.  
  1557.  A short reminder:  the pointer to the original MLE window procedure is stored 
  1558.  in the window word attached to the MLE.  This window word is retrieved at the 
  1559.  start of the MLE subclass.  So the following code makes the original 
  1560.  MLE-window procedure available. 
  1561.  
  1562.   PFNWP oldMLEProc;
  1563.   oldMLEProc = (PFNWP) WinQueryWindowULong(hwnd, QWL_USER); // Get Winproc pointer from winword
  1564.  
  1565.  Now that the pointer to the original window procedure is known, we can call 
  1566.  this procedure with the passed parameters to make sure the drop is processed 
  1567.  by the MLE. 
  1568.  
  1569.  What's next?  Let's take the problems one at the time.  First we'll define a 
  1570.  way to extract the point size from the dropped font and store it in the 
  1571.  FONTDLG structure so the right point size will show if we invoke the font 
  1572.  dialog.  This has a rather ugly penalty.  If we want to keep the point size of 
  1573.  the used font in the FONTDLG structure, we have to make this variable public. 
  1574.  Otherwise it can't be accessed in the MLE subclass as in the mormal window 
  1575.  procedure.  We will still use static in the definition because that will 
  1576.  insure that the values in the structure will be set to NULL. 
  1577.  
  1578.  The entry in the MLE subclass may look like this if we fix the point size 
  1579.  problem. 
  1580.  
  1581.   case WM_PRESPARAMCHANGED:
  1582.        {
  1583.        if ((ULONG)mpParm1 == PP_FONTNAMESIZE)
  1584.              {
  1585.              oldMLEProc(hwndMLE, msg, mpParm1, mpParm2);    // Call original MLE procedure
  1586.              CHAR  PPAttrValue[FACESIZE+64];                // PP string buffer
  1587.              WinQueryPresParam(hwndMLE,                     // Query dropped font
  1588.                                PP_FONTNAMESIZE,
  1589.                                0,
  1590.                                NULL,
  1591.                                FACESIZE+64,
  1592.                                &PPAttrValue,
  1593.                                QPF_NOINHERIT);
  1594.              //----------------------------------------------------------------------------
  1595.              // set point size in FontDlg
  1596.              //----------------------------------------------------------------------------
  1597.              char String[3];
  1598.              FontDlg.fxPointSize = (atoi(strncpy(String,
  1599.                                                  PPAttrValue,
  1600.                                                  ((ULONG)strchr(PPAttrValue,'.') -
  1601.                                                     (ULONG)PPAttrValue)
  1602.                                     )    )       ) << 16;
  1603.              return(0);
  1604.              }
  1605.        }
  1606.   break;
  1607.  
  1608.  The first part of this code sample shouldn't contain any surprises.  The 
  1609.  second part however is something different.  It's a strange brew of all sorts 
  1610.  of string functions.  (To use these string functions, we've got to include 
  1611.  string.h in the file.) 
  1612.  
  1613.  We want to retrieve the point size from the presentation parameter string. The 
  1614.  point size is represented by all the characters before the first occurence of 
  1615.  a dot (.).  So the first thing we do is extract the characters before the dot, 
  1616.  so we have a string that contains the point size in text.  To achieve this, we 
  1617.  first query the position of the dot in presentation parameter string by using 
  1618.  the strchr function.  This function returns a pointer to a substring in the 
  1619.  presentation parameter string that starts with the dot.  If we subtract the 
  1620.  pointer to the presentation parameter string from this value we get the number 
  1621.  of characters at the beginning of the presentation parameter string that 
  1622.  contain the point size. 
  1623.  
  1624.   (ULONG)strchr(PPAttrValue,'.') - (ULONG)PPAttrValue)
  1625.  
  1626.  Next the number of characters returned from the above function are copied in a 
  1627.  string from where it can be converted into a number.  The strncpy can be used 
  1628.  to copy a certain number of characters from the beginning of a string to a 
  1629.  destination string.  We can be fairly sure that the point size won't exceed 
  1630.  999, so a character string with length 3 should be enough to contain the point 
  1631.  size. 
  1632.  
  1633.   char String[3];
  1634.  
  1635.   strncpy(String, PPAttrValue,((ULONG)strchr(PPAttrValue,'.')-(ULONG)PPAttrValue));
  1636.  
  1637.  The next step is to convert the contents of the variable String to an integer. 
  1638.  This can be done immediately because the strncpy returns the pointer to 
  1639.  String.  The function normaly used to convert an ASCII string to an integer is 
  1640.  the atoi function. 
  1641.  
  1642.  However, the normal point size isn't the value we can put into a fxPointSize 
  1643.  field of a FONTDLG structure.  The fxPointsize field is of the FIXED type, 
  1644.  which is a signed integer fraction (16:16).  This means we've got to multiply 
  1645.  the point size value we found by 65536 (2^16).  An easier way to accomplish 
  1646.  this is to perform a 16 bit shift to the left (<< 16). 
  1647.  
  1648.  This leads to the following construction: 
  1649.  
  1650.   FontDlg.fxPointSize = (atoi(strncpy(String,
  1651.                                       PPAttrValue,
  1652.                                       ((ULONG)strchr(PPAttrValue,'.') -
  1653.                                          (ULONG)PPAttrValue)
  1654.                         )    )       ) << 16;
  1655.  
  1656.  This takes care of the first problem, now the second one, the fontattributes 
  1657.  that aren't set by a drop. 
  1658.  
  1659.  First we've got to check if one of the attributes is set in the presentation 
  1660.  parameter string.  Before we can do this, we've got to know how these 
  1661.  attributes are represented in the the presentation parameter string.  In one 
  1662.  of the previous sections we've seen that the attributes are appended to the 
  1663.  presentation parameter string (dot separated).  In the presentation parameter 
  1664.  string the attributes are set by the following text strings: 
  1665.  
  1666.  Italic, Outline, Strikeout, Underscore, Bold 
  1667.  
  1668.  The strstr function can be used to check if a string appears as a substring in 
  1669.  another string.  So this function is used to check for every attribute if it 
  1670.  appears in the presentation parameter string, for example for the Italic 
  1671.  attribute: 
  1672.  
  1673.   if (strstr(PPAttrValue, ".Italic"))
  1674.  
  1675.  If a attribute is found, we've got to set this in the fsSelection field of the 
  1676.  FATTRS structure so the font can be manually set by a MLM_SETFONT. 
  1677.  
  1678.  As we saw in a previous section, there are five different font attributes. 
  1679.  They are represented by the following five values: 
  1680.  
  1681.      FATTRS_SEL_ITALIC 
  1682.      FATTRS_SEL_UNDERSCORE 
  1683.      FATTRS_SEL_BOLD 
  1684.      FATTRS_SEL_STRIKEOUT 
  1685.      FATTRS_SEL_OUTLINE 
  1686.  
  1687.  Knowing this we can build a valid value for fsSelection by checking on every 
  1688.  attribute and adding these to the fsSelection. 
  1689.  
  1690.   short usfsSelection = 0;
  1691.   if (strstr(PPAttrValue, ".Italic"))
  1692.         usfsSelection = usfsSelection + FATTR_SEL_ITALIC;
  1693.   if (strstr(PPAttrValue, ".Outline"))
  1694.         usfsSelection = usfsSelection + FATTR_SEL_OUTLINE;
  1695.   if (strstr(PPAttrValue, ".Strikeout"))
  1696.         usfsSelection = usfsSelection + FATTR_SEL_STRIKEOUT;
  1697.   if (strstr(PPAttrValue, ".Underscore"))
  1698.         usfsSelection = usfsSelection + FATTR_SEL_UNDERSCORE;
  1699.   if (strstr(PPAttrValue, ".Bold"))
  1700.         usfsSelection = usfsSelection + FATTR_SEL_BOLD;
  1701.  
  1702.  If one of these attributes has been detected, the usfsSelection has a value 
  1703.  greater then 0 so we can simply check it with an if-statement.  Next we query 
  1704.  the font currently active in the MLE, (this should be the font dropped, the 
  1705.  call to oldMLEproc has set the current font.)  and change the fsSelection in 
  1706.  the FATTRS structure. 
  1707.  
  1708.   if (usfsSelection)
  1709.         {
  1710.         FATTRS fAttrs;
  1711.         WinSendMsg( hwnd, MLM_QUERYFONT, &fAttrs, NULL );
  1712.         fAttrs.fsSelection = usfsSelection;
  1713.         WinSendMsg( hwnd, MLM_SETFONT, & fAttrs, NULL );
  1714.         }
  1715.  
  1716.  This approach has one flaw:  if a font with attributes is dropped, the font 
  1717.  change can't be undone by the undo function.  This is because the font is 
  1718.  changed twice.  Once by the drop and once by the attributes set.  So if a undo 
  1719.  is invoked, only the attributes set will be undone. 
  1720.  
  1721.  The complete code for the WM_PRESPARAMCHANGED message: 
  1722.  
  1723.   case WM_PRESPARAMCHANGED:
  1724.        {
  1725.        if ((ULONG)mpParm1 == PP_FONTNAMESIZE)
  1726.             {
  1727.             oldMLEProc(hwndMLE, msg, mpParm1, mpParm2);
  1728.             CHAR  PPAttrValue[FACESIZE+64];
  1729.             WinQueryPresParam(hwndMLE,
  1730.                               PP_FONTNAMESIZE,
  1731.                               0,
  1732.                               NULL,
  1733.                               FACESIZE+64,
  1734.                               &PPAttrValue,
  1735.                               QPF_NOINHERIT);
  1736.             //----------------------------------------------------------------------------
  1737.             // set pointsize in FontDlg
  1738.             //----------------------------------------------------------------------------
  1739.             char String[3];
  1740.             FontDlg.fxPointSize = (atoi(strncpy(String,
  1741.                                                 PPAttrValue,
  1742.                                                 ((ULONG)strchr(PPAttrValue,'.') -
  1743.                                                    (ULONG)PPAttrValue)
  1744.                                    )    )       ) << 16;
  1745.             //----------------------------------------------------------------------------
  1746.             // set attributes in MLE and in FontDlg FATTRS]
  1747.             //----------------------------------------------------------------------------
  1748.             short usfsSelection = 0;
  1749.             if (strstr(PPAttrValue, ".Italic"))
  1750.                   usfsSelection = usfsSelection + FATTR_SEL_ITALIC;
  1751.             if (strstr(PPAttrValue, ".Outline"))
  1752.                   usfsSelection = usfsSelection + FATTR_SEL_OUTLINE;
  1753.             if (strstr(PPAttrValue, ".Strikeout"))
  1754.                   usfsSelection = usfsSelection + FATTR_SEL_STRIKEOUT;
  1755.             if (strstr(PPAttrValue, ".Underscore"))
  1756.                   usfsSelection = usfsSelection + FATTR_SEL_UNDERSCORE;
  1757.             if (strstr(PPAttrValue, ".Bold"))
  1758.                   usfsSelection = usfsSelection + FATTR_SEL_BOLD;
  1759.  
  1760.             if (usfsSelection)
  1761.                   {
  1762.                   FATTRS fAttrs;
  1763.                   WinSendMsg( hwnd, MLM_QUERYFONT, &fAttrs, NULL );
  1764.                   fAttrs.fsSelection = usfsSelection;
  1765.                   WinSendMsg( hwnd, MLM_SETFONT, & fAttrs, NULL );
  1766.                   }
  1767.              return(0);
  1768.              }
  1769.         }
  1770.   break;
  1771.  
  1772.  Building an Editor ( Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  1773.  
  1774.  
  1775. ΓòÉΓòÉΓòÉ 6.6. Saving information in OS2.INI ΓòÉΓòÉΓòÉ
  1776.  
  1777.  Saving information in OS2.INI 
  1778.  
  1779. It's a pain, constantly having to change the font settings if an application is 
  1780. started.  So let's have some more fun with the MLE and look at an easy way to 
  1781. save the font information used in the MLE editor.  The method described here 
  1782. will only be used to save font information in the OS2.INI file so the last font 
  1783. used in the editor will automatically be loaded as the editor is started again. 
  1784. However, roughly the same method is used in the SMALLED application to save 
  1785. font information in the extended attributes of text files. This way font 
  1786. information can be stored with a file while this information isn't stored in 
  1787. the file! 
  1788.  
  1789. When we're at it, we'll take a small detour and take a look at how the window 
  1790. size and position can be saved in the OS2.INI. 
  1791.  
  1792. Most applications will have to save some general information at one time or 
  1793. another.  In the old DOS days this kind of information was stored in a setup 
  1794. file which was read when the application was started.  The problem with these 
  1795. kind of files was that every developer invented the wheel again and took his 
  1796. own approach.  When OS/2 came along a structured method for storing this kind 
  1797. of information was provided in the profile API.  Through the profile function 
  1798. calls a programmer can create a private profile for an application or store 
  1799. information in the OS/2.INI file. 
  1800.  
  1801. The OS2.INI file is a general profile for applications under OS/2.  This file 
  1802. is read at boot time and is available in memory, so fast access is insured. 
  1803.  
  1804. The OS/2 profile files (INI files) are stored in a binary format and are 
  1805. accessable in a sort off database like fashion.  The general form in which data 
  1806. is stored in a profile looks has a three level layout. 
  1807.  
  1808. Application name
  1809.         Key name
  1810.                 Key Data
  1811.         Key name
  1812.                Key data
  1813.        :
  1814.        :
  1815.        Key name
  1816.               Key data
  1817.  
  1818. Application name
  1819.        :
  1820.        :
  1821.  
  1822. In a INI file more application names can be present.  Under every application 
  1823. data can be stored under a key name.  The form for this data is free.  It can 
  1824. be a long, a character string, a structure etc.  as long as it doesn't exceed 
  1825. the 64 Kb limit. 
  1826.  
  1827. Now we know that data can be stored and retrieved (we will see exactly how in a 
  1828. minute) in any form we like, we have to find a convenient way to store font 
  1829. data. 
  1830.  
  1831. We have two options:  we can save the font information as a FATTRS structure or 
  1832. to save it as presentation parameter information.  The FATTRS structure has as 
  1833. disadvantage that we can't save the point size.  To cope with this a 
  1834. FONTMETRICS structure has to be used.  This is a bad case off overkill for the 
  1835. simple effect we want to achieve.  Using presentation parameter information has 
  1836. the advantage that we've already got a routine process this information.  So a 
  1837. call to WinSetPresParam is enough.  The first step in saving font information 
  1838. is building a function that can build a presentation parameter string from the 
  1839. FATTRS information that can be retrieved from the MLE and the point size 
  1840. information from the FONTDLG structure.  The information about how a 
  1841. presentation parameter string looks can be found in the section Desecting the 
  1842. Font presentation parameter. 
  1843.  
  1844. Filling a string with values is rather easy, we can simply use the sprintf 
  1845. statement. 
  1846.  
  1847. // FontDlg == Global
  1848. CHAR  PPAttrValue[FACESIZE+64];                      // PP string
  1849. FATTRS fAttrs;                                       // Font information
  1850. WinSendMsg( hwndMLE, MLM_QUERYFONT, &fAttrs, NULL ); // Query current font
  1851. sprintf(PPAttrValue, "%d.%s", FontDlg.fxPointSize >> 16, fAttrs.szFacename);
  1852.  
  1853. This code sample isn't too hard.  The only thing we've got to take note off are 
  1854. the dots used in the presentation parameter and the right shift of the 
  1855. fxPointsize value to obtain a valid point size. 
  1856.  
  1857. There is still one thing missing from the presentation parameter string 
  1858. composed in this way:  this is the font attributes (if used).  To find out if 
  1859. an attribute is used in a font we conduct bitwise and on the fAttrs.fsSelection 
  1860. value with all the possible attribute values.  If an attribute is found we 
  1861. simply add it to ppAttrValue.  The code to achieve this looks like this: 
  1862.  
  1863. if (fAttrs.fsSelection & FATTR_SEL_ITALIC)
  1864.        strcat(PPAttrValue,".Italic");
  1865. if (fAttrs.fsSelection & FATTR_SEL_OUTLINE)
  1866.        strcat(PPAttrValue,".Outline");
  1867. if (fAttrs.fsSelection & FATTR_SEL_STRIKEOUT)
  1868.        strcat(PPAttrValue,".Strikeout");
  1869. if (fAttrs.fsSelection & FATTR_SEL_UNDERSCORE)
  1870.        strcat(PPAttrValue,".Underscore");
  1871. if (fAttrs.fsSelection & FATTR_SEL_BOLD)
  1872.        strcat(PPAttrValue,".Bold");
  1873.  
  1874. Now that we have a way to build a presentation parameter string from the 
  1875. available font information, let's take a look at how we can save this 
  1876. information in the OS/2 INI file.  Before we talk code we have to find a 
  1877. convenient place in the program flow where we can perform this save.  In 
  1878. moments like this you really come to love OS/2.  It has a message 
  1879. WM_SAVEAPPLICATION message that is sent when the application is about to shut 
  1880. down.  We want to save the font information at shutdown time, so this message 
  1881. is all we need. 
  1882.  
  1883. Note:  Make sure that the WinDefWindowProc is called after you process this 
  1884. message! 
  1885.  
  1886. There are two functions that can be used to write data to a profile: 
  1887. PrfWriteProfileData for binary data and PrfWriteProfileString for a character 
  1888. string, which is what we're interested in.  The syntax looks like this: 
  1889.  
  1890. HINI  hini;     // Initialization-file handle
  1891. PSZ   pszApp;   // Application name
  1892. PSZ   pszKey;   // Key name
  1893. PSZ   pszData;  // Text string
  1894. BOOL  fSuccess; // Success indicator
  1895.  
  1896. fSuccess = PrfWriteProfileString(hini,
  1897.                                  pszApp,
  1898.                                  pszKey,
  1899.                                  pszData);
  1900.  
  1901. For HINI we got to obtain initialization handle if we want to use a private 
  1902. profile.  However if we are using the OS2.INI file we can use a predefined 
  1903. handle, HINI_USERPROFILE. 
  1904.  
  1905. To fill the pszApp and the pszKey values, it is good practice to add defines in 
  1906. the header file.  So you can be sure that the same entries are used for storing 
  1907. as well as receiving data. 
  1908.  
  1909. //----------------------------------------------
  1910. // In editor3.h
  1911. //----------------------------------------------
  1912. #define SAVE_NAME  "EDITOR3"
  1913. #define PPFONT     "PPFONT"
  1914.  
  1915. //----------------------------------------------
  1916. // During WM_SAVEAPPLICATION
  1917. //----------------------------------------------
  1918. PrfWriteProfileString(HINI_USERPROFILE,
  1919.                       SAVE_NAME,
  1920.                       PPFONT,
  1921.                       PPAttrValue);
  1922.  
  1923. I promised another small detour.  Here it is.  The most common action to take 
  1924. at WM_SAVEAPPLICATION is to save the current window size and place.  It's done 
  1925. so often that a special function has been provided.  This is the 
  1926. WinStoreWindowPos function.  A nice spin-off of this function is that it will 
  1927. save the presentation parameter parameters of the frame-window and all it's 
  1928. (added) controls.  So if we change the color of the toolbar or the font used in 
  1929. the statusbar, it will be remembered! 
  1930.  
  1931. The WinStoreWindowPos takes the handle of the window to save as a parameter, as 
  1932. well as the application name and the keyname under which this information must 
  1933. be saved.  Knowing this we can finaly write the compete code for the 
  1934. WM_SAVEAPPLICATION message. 
  1935.  
  1936. case WM_SAVEAPPLICATION:
  1937.      {
  1938.      CHAR  PPAttrValue[FACESIZE+64];                   // PP string
  1939.      FATTRS fAttrs;                                    // Font information
  1940.  
  1941.      WinSendMsg( hwndMLE, MLM_QUERYFONT, &fAttrs, NULL ); // Query current font
  1942.      sprintf(PPAttrValue,                              // Fill PP string
  1943.              "%d.%s",
  1944.              FontDlg.fxPointSize >> 16,
  1945.              fAttrs.szFacename);
  1946.  
  1947.      if (fAttrs.fsSelection & FATTR_SEL_ITALIC)        // Check on Italic attribute
  1948.             strcat(PPAttrValue,".Italic");             //
  1949.      if (fAttrs.fsSelection & FATTR_SEL_OUTLINE)       // Check on Outline attribute
  1950.             strcat(PPAttrValue,".Outline");            //
  1951.      if (fAttrs.fsSelection & FATTR_SEL_STRIKEOUT)     // Check on Strikeout attribute
  1952.             strcat(PPAttrValue,".Strikeout");          //
  1953.      if (fAttrs.fsSelection & FATTR_SEL_UNDERSCORE)    // Check on Underscore attribute
  1954.             strcat(PPAttrValue,".Underscore");         //
  1955.      if (fAttrs.fsSelection & FATTR_SEL_BOLD)          // Check on Bold attribute
  1956.             strcat(PPAttrValue,".Bold");
  1957.  
  1958.      PrfWriteProfileString(HINI_USERPROFILE,           // Save font PP in OS2.INI
  1959.                           SAVE_NAME,
  1960.                           PPFONT,
  1961.                           PPAttrValue);
  1962.  
  1963.      WinStoreWindowPos(SAVE_NAME,                      // Save window size and position
  1964.                        SAVE_WINPOS,
  1965.                        WinQueryWindow(hwnd,QW_PARENT));// Query frame handle
  1966.      }
  1967. break;
  1968.  
  1969. Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  1970.  
  1971.  
  1972. ΓòÉΓòÉΓòÉ 6.7. Retrieving Font Information from OS2.INI ΓòÉΓòÉΓòÉ
  1973.  
  1974.  Retrieving Font Information from OS2.INI 
  1975.  
  1976. Saving the font and size/position information is one thing, we also need to 
  1977. retrieve this information the moment the editor is started. 
  1978.  
  1979. The size/position information has to be loaded after the window is started, but 
  1980. before it becomes visible.  Also the MLE window and the statusbar window must 
  1981. be created because they participate in the WM_FORMAT and the WM_SIZE message. 
  1982.  
  1983. The font information must be handled in the same fashion.  It must be loaded 
  1984. after the MLE window is loaded, but before any file information is shown (for 
  1985. example a file drop on the editor icon). 
  1986.  
  1987. Normaly this kind of action would be handled during the WM_CREATE message. 
  1988. However in this case the MLE doesn't exist during the WM_CREATE.  In EDITOR2 we 
  1989. have chosen to create the MLE window directly after the main frame window. The 
  1990. WM_CREATE message is send by the creation of the frame window, so this isn't a 
  1991. good spot. 
  1992.  
  1993. The ideal spot, in our opinion, is right after the toolbar is loaded. 
  1994.  
  1995. To restore the window size and place (and the presentation parameter attached 
  1996. to all it's controls) we use the WinSetWindowPos function.  This function will 
  1997. look in the OS2.INI file for a given application and key name and restore the 
  1998. information previously saved by a WinStoreWindowPos call. 
  1999.  
  2000. WinRestoreWindowPos(SAVE_NAME,
  2001.                     SAVE_WINPOS,
  2002.                     hwndFrame);
  2003.  
  2004. Making the call just like this isn't enough.  If WinRestoreWinPos does find the 
  2005. stored information in the INI file, it applies it to the window identified by 
  2006. hwndFrame.  It doesn't show the window or activate it.  To accomplish this we 
  2007. have to make another call.  The WinSetWindowPos function (a very nice function 
  2008. to know about) can be used to make the window visible, activate the window and 
  2009. place it on top of the z-order. 
  2010.  
  2011. We know if the WinRestoreWinPos function had been succesfull if it returns a 
  2012. TRUE.  If it didn't retrieve any information from the OS2.INI file (for example 
  2013. during the first time editor3 is started) we have to set the size and place 
  2014. ourselves.  The following piece of code will take care of business. 
  2015.  
  2016. //---------------------------------------------------------------------------------------------
  2017. // Set Main window (Frame) size and position
  2018. //---------------------------------------------------------------------------------------------
  2019. if (WinRestoreWindowPos(SAVE_NAME,           // Get and set size en place from OS2.INI
  2020.                         SAVE_WINPOS,         //
  2021.                         hwndFrame))          //
  2022.  
  2023.      WinSetWindowPos(hwndFrame,              // Activate window
  2024.                      HWND_TOP,               //
  2025.                      0,0,0,0,                // (PM will position through WinRestoreWondowPos)
  2026.                      SWP_ACTIVATE |          // Activate window
  2027.                      SWP_SHOW);              // Show Window else
  2028.      WinSetWindowPos(hwndFrame,              // If no entry in OS2.INI
  2029.                      NULLHANDLE,             // default position 10,10
  2030.                      10,10,600,400,          // with SIZE 600,400
  2031.                      SWP_ACTIVATE|SWP_MOVE|  //
  2032.                      SWP_SIZE    |SWP_SHOW); //
  2033.  
  2034. For setting the font information we have to use another function.  We saved the 
  2035. font information by calling the PrfWriteProfileString function.  This 
  2036. information can be retrieved by calling the counterpart of this function, the 
  2037. PrfQueryProfileString.  This function will look into the OS2.INI file for the 
  2038. given application and key, if it doesn't find it, it will return a default 
  2039. value. 
  2040.  
  2041. HINI   hini;          // Initialization-file handle
  2042. PSZ    pszApp;        // Application name
  2043. PSZ    pszKey;        // Key name
  2044. PSZ    pszDefault;    // Default string
  2045. PVOID  pBuffer;       // Profile string
  2046. ULONG  cchBufferMax;  // Maximum string length
  2047. ULONG  pulLength;     // String length returned
  2048.  
  2049. pulLength = PrfQueryProfileString(hini,
  2050.                                   pszApp,
  2051.                                   pszKey,
  2052.                                   pszDefault,
  2053.                                   pBuffer,
  2054.                                   cchBufferMax);
  2055.  
  2056. For the default value we can define a presentation parameter string that 
  2057. contains the standard system font. 
  2058.  
  2059. "12.System Proportional" 
  2060.  
  2061. If no value is found, the MLE is set to the default system font.  Once a value 
  2062. is retrieved we've got to set it.  To set a font through a presentation 
  2063. parameter we've got to use the WinSetPresParam function. 
  2064.  
  2065. HWND   hwnd;            // Window handle           (MLE handle)
  2066. ULONG  idAttrType;      // Attribute type identity (PP_FONTNAMESIZE)
  2067. ULONG  cbAttrValueLen;  // Byte count of the data passed in the pAttrValue parameter
  2068. PVOID  pAttrValue;      // Attribute value
  2069. BOOL   fSuccess;        // Success indicator
  2070.  
  2071. fSuccess = WinSetPresParam(hwnd,
  2072.                            idAttrType,
  2073.                            cbAttrValueLen,
  2074.                            pAttrValue);
  2075.  
  2076. The beauty of using this function is that it will automatically invoke the 
  2077. WM_PRESPARAMCHANGED message.  So all the right moves will be made to initiate 
  2078. the point size value in the FontDlg variable and set the fAttrs value in the 
  2079. MLE control.  Even previously set bold and italic attributes will be handled 
  2080. correctly. 
  2081.  
  2082. //---------------------------------------------------------------------------------------------
  2083. // Set font from the value in OS2.INI
  2084. //---------------------------------------------------------------------------------------------
  2085. char PPAttrValue[FACESIZE+64];
  2086. PrfQueryProfileString(HINI_USERPROFILE,
  2087.                       (PSZ) SAVE_NAME,
  2088.                       (PSZ) PPFONT,
  2089.                       (PSZ) "12.System Proportional",
  2090.                       (PVOID) PPAttrValue,
  2091.                       (ULONG) FACESIZE+64);
  2092.  
  2093. WinSetPresParam(hwndMLE, PP_FONTNAMESIZE, strlen(PPAttrValue)+1, PPAttrValue);
  2094.  
  2095. Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2096.  
  2097.  
  2098. ΓòÉΓòÉΓòÉ 6.8. Concluding notes ΓòÉΓòÉΓòÉ
  2099.  
  2100.  Concluding notes 
  2101.  
  2102. This is the third (and probably the last) article in a describing a way to 
  2103. build a small fast editor that can easily be embedded in another application. 
  2104. We know it isn't complete yet.  For example, search and replace is a serious 
  2105. omission.  We hope the articles will be useful for your own program 
  2106. development.  (We received some mail stating so [grin] .) The articles about 
  2107. the MLE editor are for a large part based on the SMALLED application.  This 
  2108. application is available as share/freeware on the Hobbes ftp site.  Currently 
  2109. it's at version 0.96 and can be retrieved as SMALED96.ZIP. 
  2110.  
  2111. The EDITOR3 program can be made somewhat simpler if you use the easy toolbar 
  2112. described in EDM3-8 'Easy Buttonbars'.  Besides that I (Eric) am planning 
  2113. another article based on easy buttonbars to add bubble help to a buttonbar. 
  2114. Bubble help is a popup window under the buttonbar containing help info about a 
  2115. button if you mouse over it.  So further enhancement based on what we've 
  2116. written for EDM/2 is possible. 
  2117.  
  2118. Feel free to use the code any way you like and send us your comments. 
  2119.  
  2120. The examples are all build and compiled with Borland C++ 2.0. 
  2121.  
  2122. Building an Editor (Part 3) - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2123.  
  2124.  
  2125. ΓòÉΓòÉΓòÉ 7. C++ Compiler Review (Part 3) ΓòÉΓòÉΓòÉ
  2126.  
  2127. C++ Compiler Review 
  2128.  
  2129. Written by Gordon Zeglinski 
  2130.  
  2131. There were a few typos in the C/C++ compiler review benchmark tables presented 
  2132. in the last issue. Revised tables including the results of the Watcom 10.5 
  2133. benchmarks will be included in this issue. Watcom 10.5 benchmarks you ask? Yes 
  2134. due to the number of questions I have gotten about Watcom 10.5, in this issue, 
  2135. we will look at what's new in Watcom version 10.5. 
  2136.  
  2137. C++ Compiler Review - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2138.  
  2139.  
  2140. ΓòÉΓòÉΓòÉ 7.1. What's new in Watcom C/C++ 10.5? ΓòÉΓòÉΓòÉ
  2141.  
  2142. What's new in Watcom C/C++ 10.5? 
  2143.  
  2144. According to the registration card, anyone registering version 10.5 will be 
  2145. mailed a copy of Watcom 10.6. 10.6 will offer more Win95 support (yuck :>). 
  2146. Features that are different or are not found in version 10 are considered to be 
  2147. new. 
  2148.  
  2149. For the OS/2 programmer, 10.5 features better warp support. The debugger and 
  2150. sampler (used in profiling code) run better under Warp than their 10a 
  2151. counterparts. Although they still have problems dealing with multi-threaded PM 
  2152. programs. Remote debugging of OS/2, Win NT/95 through tcp/ip is now possible. 
  2153. For those doing 16 bit OS/2 programming the OS/2 1.x toolkit is now included as 
  2154. well. This compiler can now be used to generate tcp/ip applications. 
  2155.  
  2156. For the Windows programmer, Win95 support has been added. Also, the NT 3.5 
  2157. toolkit is included. MFC 3.0 support and a new visual programmer have been 
  2158. added. The visual programmer is used to build MFC applications. The editor now 
  2159. includes source revision control hooks. 
  2160.  
  2161. Improvements of a general nature include a new install program, native C++ 
  2162. exception handling, the ability to browse C code, and better compatibility with 
  2163. the Microsoft compiler. 
  2164.  
  2165. Although the sampler and profiler are not new. It is new that they run under 
  2166. Warp. So we'll take a peek at what the sampler/profiler have to offer. 
  2167.  
  2168. The profiler displays info about time usage in various levels of detail. The 
  2169. highest level displays the usage based upon compilation unit. The next level 
  2170. displays the time usage for functions in a particular module. Finally, the 
  2171. third level displays the time usage for the lines of a particular function. The 
  2172. lack of thread specific support severely limits the use of the profiler in any 
  2173. multi-threaded OS. 
  2174.  
  2175. C++ Compiler Review - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2176.  
  2177.  
  2178. ΓòÉΓòÉΓòÉ 7.2. Benchmarks ΓòÉΓòÉΓòÉ
  2179.  
  2180. Benchmarks 
  2181.  
  2182. To allow easy comparison, the complete set of benchmark tables will be included 
  2183. here with Watcom 10.5 added. Note: the Watcom seive time reported in the last 
  2184. issue was incorrect. 
  2185.  
  2186. The following table shows the results of the C benchmarks: 
  2187.  
  2188. Compiler   bsort   sieve   dhry21   whetstone(S)   whetstone(D)   Rolled      Rolled      Unrolled    Unrolled
  2189.                                                                   Linpack(S)  Linpack(D)  Linpack(S)  Linpack(D)
  2190.  
  2191. Metaware   2.468   4.218   62500.0    142857         111111         3135        2194         3135       2312
  2192. VAC++      2.219   3.750   58139.5     34482          34482         2928        1996         2928       2090
  2193. Watcom     1.970   4.090   65789.5    111111          76923         2922        1990         3121       2328
  2194. Wat 10.5   2.190   4.25    54347.8     90909         125000         2591        2081         3121       2215
  2195. Borland    2.406   6.062   32467.5     17241          17241         2444        1758         2586       1829
  2196.  
  2197. The units for the C benchmarks are as follows. Bsort and Sieve are in seconds 
  2198. (the smaller the number the better). Dryh21 is in Dhrystones/sec. The two 
  2199. whetstone tests are in KWhets/sec. All the Linpack tests are in KFlops. Except 
  2200. for the first two benchmarks, larger numbers are better. 
  2201.  
  2202. Watcom 10.5 performed both better and worse than Watcom 10a in the C benchmark 
  2203. suit. Overall it performed somewhat worse than version 10a. 
  2204.  
  2205. The following table show the results of the C++ benchmark. 
  2206.  
  2207. Compiler   Test 1    Test 2   Test 3    Test 4   Test 5
  2208.  
  2209. Metaware    3.187     8.531   2.938     33.406   10.344
  2210. VAC++       2.187      NA     2.282    460.156     NA
  2211. Watcom      3.090    18.720   4.910     93.400   20.970
  2212. Wat 10.5    2.84     17.63    4.93      95.79    19.34
  2213. Borland     3.406      NA     3.032    825.344     NA
  2214.  
  2215. Test 1 simply tests the construction and destruction of an object including a 
  2216. call to it's virtual function. Test 2 is like test 1 except a more complex 
  2217. object is used. Test 3 is similar to test 1 except that the object is 
  2218. created/destroyed from within a try/catch block. Test 4 is like test 3 except 
  2219. that an exception is actually thrown and caught. Test 5 assigns the complex 
  2220. object to another object. The same complex object that was used in test 2 is 
  2221. used here. 
  2222.  
  2223. Test 3 uses 1 less function call than test 1. In theory, it should use up less 
  2224. time than test 1 unless the amount of time used to setup the try/catch block 
  2225. exceeds that of a function call. In both the Metaware and Borland test results, 
  2226. test 3 was faster than test 1. 
  2227.  
  2228. In the C++ test suit, Watcom 10.5 performed better than version 10a in every 
  2229. test except those involving C++ exceptions. It seems the new C++ exception 
  2230. handling code in 10.5 performs slightly worse than the code in version 10a. 
  2231.  
  2232. The following table shows the compilation time and executable size for the C++ 
  2233. bench mark program. Notice the compile time and executable size decrease 
  2234. comparing version 10a and 10.5. 
  2235.  
  2236. Compiler   Compile+Link Time (s)      EXE size (bytes)
  2237.  
  2238. Metaware        59.19                  80400
  2239. VAC++           35.35                  39936
  2240. Watcom          84.63                  65898
  2241. Wat 10.5        57.22                  59269
  2242. Borland         14.22                  41489
  2243.  
  2244. The unzip test compares the compilation time, executable speed, and executable 
  2245. size for Info unzip version 5.12. The following table shows the results of the 
  2246. unzip test. 
  2247.  
  2248. Compiler   Compile+Link (s)   'unzip -t unzip512.zip >NUL' (s)  EXE size (bytes)
  2249.  
  2250. Metaware      629.47                 2.37                          128579
  2251. VAC++         189.10                 2.50                          136755
  2252. Watcom        232.22                 2.07                           96027
  2253. Wat 10.5      231.91                 2.13                           96245
  2254. Borland       168.53                 2.40                          140339
  2255.  
  2256. Note: although VAC++ compiled unzip faster than Watcom, this is may or may not 
  2257. be the case. VAC++ takes twice as long to compile the AdeptXBBS source code. 
  2258. Automatic function inlining had to be turned off in VAC++ because the resulting 
  2259. EXE falsely reported error in a good zip file. Metaware had inlining turned on. 
  2260.  
  2261. C++ Compiler Review - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2262.  
  2263.  
  2264. ΓòÉΓòÉΓòÉ 7.3. Summary ΓòÉΓòÉΓòÉ
  2265.  
  2266. Summary 
  2267.  
  2268. The upgrade to Watcom 10.5 is worthwhile. Compared to version 10a, one gains 
  2269. remote OS/2 debugging, better performance under warp (although not perfect 
  2270. yet), and faster C++ compilation times. For those doing tcp/ip programs, 
  2271. there's finally a alternative to CSet and EMX (a freeware C/C++ compiler). The 
  2272. cross platform support is great. 
  2273.  
  2274. Watcom 10.5 works well enough to be the choice for a general purpose OS/2 
  2275. compiler. It's not a perfect package however, it's extremely versatile and 
  2276. reasonably priced. Personally, I still prefer using CSet++ 2.1 for debugging 
  2277. and analyzing code performance. The debugger and profiler in CSet++ 2.1 work 
  2278. well and do so in a reasonable amount of memory. 
  2279.  
  2280. C++ Compiler Review - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2281.  
  2282.  
  2283. ΓòÉΓòÉΓòÉ 8. OS/2 Frequently Asked Questions ΓòÉΓòÉΓòÉ
  2284.  
  2285. OS/2 Frequently Asked Questions 
  2286.  
  2287. Written by Dean Roddey 
  2288.  
  2289. Introduction 
  2290.  
  2291. As someone who spends a considerable amount of time in the CIS OS/2 developer's 
  2292. forum and in the OS/2 developer news groups, I've seen that there are a core 
  2293. set of PM questions that are asked time and time again.  The obvious reason for 
  2294. this pattern is surely the lack of practical documentation on these subjects 
  2295. I'm sure.  Since EDM/2 is geared towards filling this hole in IBM's 
  2296. documentation, I thought I would add my two cents and answer these questions in 
  2297. as practical and (hopefully) unconvoluted a manner as possible. 
  2298.  
  2299. The Subjects of This Article 
  2300.  
  2301. I will cover a number of topics in this section that rotate around one or other 
  2302. popular misconception or obscurity related to PM programming.  They are not in 
  2303. any particular ranking or order necessarily.  (well ok they are are 
  2304. alphabetically arranged.)  Here is a list of the topics covered: 
  2305.  
  2306.      Changing Window Styles 
  2307.      Dialogs as Main Windows 
  2308.      Dialog User Interaction (and how to do it yourself) 
  2309.      PM Resources and Resource Ids 
  2310.      Presentation Parameters and System Colors 
  2311.      Subclassing/Superclassing 
  2312.      Transparent Windows 
  2313.      Window Extra Data 
  2314.      Window Messages 
  2315.      Window Relationships 
  2316.  
  2317.  OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2318.  
  2319.  
  2320. ΓòÉΓòÉΓòÉ 8.1. Changing Window Styles ΓòÉΓòÉΓòÉ
  2321.  
  2322.  Changing Window Styles 
  2323.  
  2324. A very commonly asked question is "Can I change a window's styles after it's 
  2325. created?"  The answer is maybe, maybe not.  It depends upon the particular type 
  2326. of window.  There is, unfortunately, no standard mechanism for doing this kind 
  2327. of thing.  So it becomes just a matter of experience as to what styles you can 
  2328. manipulate after the fact. 
  2329.  
  2330. In a Perfect World 
  2331.  
  2332. The obvious solution to this issue would be a formalized mechanism through 
  2333. which window styles can be modified, and through which a window could indicate 
  2334. to a client application what styles it will allow to be changed.  For instance 
  2335. a WinSetWindowStyles() method would take a window handle, a set of new styles, 
  2336. and a relevant bits mask.  It would get the current styles, weave in the new 
  2337. ones, and then send a message to the window telling it the new styles 
  2338. (WM_NEWSTYLES perhaps.)  The window would look at the current styles and new 
  2339. styles, update itself with the ones it would accept, and return to PM the 
  2340. changes it could do.  PM would return these to the client code.  The update 
  2341. would be as efficient as possible since the window would know what parts of 
  2342. itself were affected. 
  2343.  
  2344. In Reality 
  2345.  
  2346. However, there is no such thing in PM.  To a PM window, its styles are just a 
  2347. set of bit flags put into a predefined place in the window's extra data words 
  2348. (see Window Extra Data below.)  During window creation, PM will place the 
  2349. styles (passed to WinCreateWindow) into this area.  After that, there is no 
  2350. formalized usage of the styles flags.  Each class of window is free to do one 
  2351. of 3 things. 
  2352.  
  2353.      Look at the styles on every paint and paint itself accordingly 
  2354.      Look at the styles upon creation and ignore them for evermore 
  2355.      Look at some style bits in manner #1 and some in manner #2 
  2356.  
  2357.  Many simple window classes can work purely on the first 'stateless' principle. 
  2358.  On each paint it just looks at its current styles and paints accordingly.  For 
  2359.  these types of windows, the window styles can be easily modified by extracting 
  2360.  the current styles, modifying them as desired, putting them back, and 
  2361.  invalidating the whole window (unless you know for a fact that only a 
  2362.  particular area of the window is affected and can successfully calculate it.) 
  2363.  This is obviously less desirable than the perfect world, since often this 
  2364.  scheme will cause gratuitous repainting which is unsightly and wasteful of CPU 
  2365.  time.  But at least it can be done. 
  2366.  
  2367.  Some window classes only look at certain styles once at creation and then 
  2368.  never bother to check them again.  The most obvious example is when a 
  2369.  particular window class can optionally create child windows (such as scroll 
  2370.  bars.)  Once those scroll bars are created, there is no real reason to look at 
  2371.  those styles again, at least from the window's perspective.  One reason for 
  2372.  taking this approach is the very lack of a formalized mechanism for updating 
  2373.  styles.  For most controls, the only thing they can really do is look at the 
  2374.  styles during a paint.  But, for doing things like creating/destroying/moving 
  2375.  child controls and whatnot, the paint event is not a very good place to do 
  2376.  such things. 
  2377.  
  2378.  Frame Controls 
  2379.  
  2380.  Unlike normal window styles, frames do have a formal mechanism (separate from 
  2381.  the window styles system) for addition and subtraction of standard frame 
  2382.  controls.  So, for the most part, you can cause them to come and go as you 
  2383.  please.  You just need to destroy unwanted ones or create new desired ones and 
  2384.  then send a WM_UPDATEFRAME message with bits on for the controls you deleted 
  2385.  or want added.  Be sure to give them the correct FID_XXX window ids and make 
  2386.  the frame their parent and owner, though some frame controls are not separate 
  2387.  windows and have no id. 
  2388.  
  2389.  Confusingly enough, the frame window class has styles for most of the frame 
  2390.  controls; but, you should only use them from a dialog resource (or so the 
  2391.  documentation states.)  When creating a frame via WinCreateStdWindow() or 
  2392.  WinCreateWindow(), you should use the FCF_xxxx values.  These are passed in 
  2393.  via a FRAMECDATA structure as the window control data. 
  2394.  
  2395.  OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2396.  
  2397.  
  2398. ΓòÉΓòÉΓòÉ 8.2. Dialogs as Main Windows ΓòÉΓòÉΓòÉ
  2399.  
  2400.  Dialogs as Main Windows 
  2401.  
  2402. Lots of people ask about how to use dialog windows as main windows.  The 
  2403. reasons are obvious, such as being able to draw the windows instead of doing 
  2404. time consuming positioning calculations and creating them on the fly.  Also, 
  2405. you get the benefit of having the window sized to fit the default system font 
  2406. on the target hardware.  A main window dialog is definitely doable, and it's 
  2407. pretty easy.  But there are a number of different approaches to do it, each of 
  2408. which has its own pros and cons. 
  2409.  
  2410. Everyone has used WinDlgBox() to run dialogs but, to understand the best way to 
  2411. use dialogs as main windows, you need to understand what goes on under the hood 
  2412. when you call it.  Basically two APIs, WinLoadDlg() and WinProcessDlg() make up 
  2413. the guts of WinDlgBox(), with some extra housekeeping in between.  So first a 
  2414. quick overview of what happens when you create a dialog. 
  2415.  
  2416. How Dialogs Work 
  2417.  
  2418. The WinLoadDlg() API uses DosGetResource() to load up the dialog description of 
  2419. your dialog (see PM Resources and Resource Ids below) from the resources left 
  2420. in the DLL or EXE by the resource compiler.  It uses this description to create 
  2421. a frame window and all of the individual controls defined by the dialog.  The 
  2422. controls are created in the same order as you put them in the dialog, which 
  2423. becomes important below.  Once everything is created it will subclass the frame 
  2424. using your dialog procedure (see Subclassing and Superclassing below) and send 
  2425. you a WM_INITDLG message. 
  2426.  
  2427. Once done with all of that, WinLoadDlg() destroys the dialog definition buffer 
  2428. and returns.  Note that it only creates the windows and gets everything set up 
  2429. but nothing else.  The frame was left invisible so you don't see it yet (unless 
  2430. you showed it during WM_INITDLG processing.)  At this point, the frame window 
  2431. is no different than if you had manually created it, and its controls, 
  2432. yourself.  So, as far as windows go, a dialog is very literally a frame window. 
  2433. It is only special in the fact that it is subclassed by a cooperative party 
  2434. (you) and that it is processed differently.  You are the cooperative party in 
  2435. that you voluntarily pass any unhandled messages to WinDefDlgProc(). Much of 
  2436. the magic of dialogs is really in WinDefDlgProc().  It provides the standard 
  2437. dialog style responses to incoming user and system input.  If you did not pass 
  2438. messages to WinDefDlgProc() then you would not get any of the standard dialog 
  2439. reactions. 
  2440.  
  2441. Modal Message Loops 
  2442.  
  2443. When a dialog is being processed, you've probably noticed that it will not let 
  2444. any input go to the other windows of the program.  It is in a 'modal message 
  2445. loop'.  When you run a dialog, your message loop is no longer being used. 
  2446. Instead, a message loop inside PM is getting input.  This gives it control over 
  2447. where user input messages go to or if they are allowed to go anywhere at all, 
  2448. since input messages are always posted and therefore come in via a message 
  2449. loop) . 
  2450.  
  2451. The WinProcessDlg() call is what provides this modal loop.  It does the usual 
  2452. WinGetMsg() and WinDispatchMsg() calls, but also watches for dialog specific 
  2453. circumstances such as the dismissal of the dialog.  WinDismissDlg() does two 
  2454. things, it stores the caller's return code parameter in the frame's extra 
  2455. window word (at QWS_RESULT) and sets the FF_DLGDISMISSED flag in the frame's 
  2456. QWS_FLAGS window words.  WinProcessDlg() will check the dismiss flag and see 
  2457. that its time to return.  So it will pull the result code from the window's 
  2458. extra data and return it to the caller as the result code of the dialog. 
  2459.  
  2460. Theoretically, you could clear the dismissed flag and call WinProcessDlg() 
  2461. again to start up the dialog again.  But it would look ugly because the dismiss 
  2462. would hide the dialog and then it would reappear again.  I have not tried it 
  2463. myself, but you can give it a try if you think it would be useful. 
  2464.  
  2465. Also, you could theoretically create a frame, and any desired control windows 
  2466. within it, subclass it to a dialog procedure and then call WinProcessDlg() to 
  2467. process it modally as a dialog.  WinProcessDlg() probably wouldn't know or care 
  2468. that the windows were created manually instead of as a dialog resource.  Just 
  2469. be sure that you subclass it to a window procedure that is written like a 
  2470. dialog procedure, i.e.  it uses WinDismissDlg() and passes unhandled messages 
  2471. to WinDefDlgProc(). 
  2472.  
  2473. WinProcessDlg() does not destroy the window when it returns, but it does make 
  2474. it invisible.  If you use the separate load and process steps yourself, then 
  2475. you must destroy the dialog frame.  If you called WinDlgBox() it will destroy 
  2476. the frame before it returns, and it will pass on back to you the return that 
  2477. came back from WinProcessDlg(). 
  2478.  
  2479. The Easy Way Out 
  2480.  
  2481. The easiest way to have a dialog as a main window is to just do the usual 
  2482. WinInitialize() and WinCreateMsgQueue(), then use WinDlgBox() to run a dialog. 
  2483. When it returns, terminate and exit.  Having the dialog do all the work is 
  2484. nice, but it is also the reason why this is sometimes not the best way to do a 
  2485. main window as a dialog.  For starters you don't have a lot of control and some 
  2486. of the standard dialog processing is not really appropriate for main windows. 
  2487. For instance: 
  2488.  
  2489.    1. Definitely don't just destroy the frame window when you use this scheme. 
  2490.       That will not cause the modal message loop to exit, but it will destroy 
  2491.       your ability to interact with your program.  So basically the program 
  2492.       will just be hung. 
  2493.  
  2494.    2. There are certain dialog'isms like the fact that pressing escape will, if 
  2495.       the WM_CHAR message gets to WinDefDlgProc(), cause a dismissal of the 
  2496.       dialog, thus exiting your program.  This is not always desired behavior 
  2497.       for a main window. 
  2498.  
  2499.    3. You cannot do the usual step of allowing the user to back out of an exit 
  2500.       because you don't have control over the message loop. 
  2501.  
  2502.  The Next Step 
  2503.  
  2504.  The next step up the ladder of complexity vs flexibility is to use the 
  2505.  WinLoadDlg() API to load up the dialog and then enter your own message loop, 
  2506.  so that you are not processing it modally.  As discussed above there is 
  2507.  nothing magic about a dialog window itself, i.e.  using WinLoadDlg() is not 
  2508.  much different from you creating the frame and controls yourself, or at least 
  2509.  the results are not.  But once you move to this non- modal dialog style, you 
  2510.  are not really a dialog any more, so you don't want to keep calling 
  2511.  WinDefDlgProc() or otherwise acting like you are still a dialog when you are 
  2512.  not.  You can still pretty much get away with such things but you might run 
  2513.  into some interesting problems.  For instance, if you just dismiss the dialog 
  2514.  on a WM_COMMAND (as a normal dialog would), you will end up with a hung 
  2515.  program (from the user's perspective.)  The dialog will be hidden but the 
  2516.  window will not be destroyed and no WM_QUIT will be issued to the message 
  2517.  queue to cause the program to exit.  There are some other small problems of 
  2518.  that sort, that are liveable but can bite you or confuse your users. 
  2519.  
  2520.  What I suggest is this.  Use WinQueryClassInfo() to query the class info for 
  2521.  the WC_FRAME class.  Remember that the class name for a standard PM controls 
  2522.  is not a real text string but a magic pointer, so the name you pass to 
  2523.  WinQueryClassInfo() is in the form "#0000x", where x is the number from the 
  2524.  defined WC_FRAME value (look in PMWin.h).  This information structure has the 
  2525.  address of the original frame class' window procedure.  If you now pass 
  2526.  unhandled messages to that procedure instead of WinDefDlgProc(), you will 
  2527.  effectively bypass the dialog specific processing and turn your dialog into a 
  2528.  regular subclassed frame window.  Keep in mind that you should still handle 
  2529.  WM_INITDLG to do any setup if you want to, but you will not see WM_CREATE 
  2530.  because the window is already created before it is subclassed to your dialog 
  2531.  procedure.  If you now just get rid of WinDismissDlg() and you have a pretty 
  2532.  normal frame window.  If you don't need the subclass anymore, for instance 
  2533.  because your dialog has a client window, you can call WinSubclassWindow() with 
  2534.  the original frame window class.  This will get rid of your subclass and save 
  2535.  processing effort in the process, since every frame message does not have to 
  2536.  go through two layers before it gets handled.  I haven't tried it but you 
  2537.  could possibly pass the original frame procedure as the dialog procedure and 
  2538.  not have to have a dialog proc at all?  You try it though and let me know, and 
  2539.  I will use it if it doesn't waste your partition table or anything.  (I'm so 
  2540.  brave.  [grin]) 
  2541.  
  2542.  As an aside, WinDefDlgProc() is really doing the same thing itself internally, 
  2543.  handling some messages and passing others on to the original frame procedure. 
  2544.  You are just skipping the middle man by doing this yourself. 
  2545.  
  2546.  Though this is the most technically correct approach, it does have one down 
  2547.  side.  You loose the automatic tabbing support that WinDefDlgProc() provides. 
  2548.  This though is very easily dealt with.  See Dialog User Interaction below for 
  2549.  a discussion of this issue. 
  2550.  
  2551.  The Ultimate Control 
  2552.  
  2553.  The ultimate control of dialogs is accomplished by manually parsing the dialog 
  2554.  resource and creating the controls yourself.  That is a pretty large subject 
  2555.  so I will not cover it here.  However you might want to read my article in the 
  2556.  July/Aug 1994 issue of 'OS/2 Developer', which covers this subject pretty 
  2557.  well.  Given the information in this article and that one, you should be able 
  2558.  to handle it with a little experimentation.  This knowledge is also useful for 
  2559.  creating your own dialog editor if you care to do such things. 
  2560.  
  2561.  I use this method in my CIDLib class libraries, which allows the TDialogWnd 
  2562.  class to be very expandable.  Its constructor provides a callout (which is 
  2563.  called for each new control parsed from the resource) so that the calling code 
  2564.  can optionally override the type or attributes of each control.  It's a pretty 
  2565.  powerful and flexible system, but without all the work of providing your own 
  2566.  screen builder (though I will probably do that eventually.)  Dialog User 
  2567.  Interaction 
  2568.  
  2569.  For various reasons, people often want to understand how tabbing in dialogs 
  2570.  works.  Sometimes, as in the previous section, they've loaded a complex dialog 
  2571.  as a main window and want to retain the tabbing capability.  Other times, they 
  2572.  have a similar complex set of controls that they have created manually and 
  2573.  want to provide tabbing for them.  This section provides some background on 
  2574.  how tabbing works and tells you how to easily provide it for yourself. 
  2575.  
  2576.  OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2577.  
  2578.  
  2579. ΓòÉΓòÉΓòÉ 8.3. Window Enumeration ΓòÉΓòÉΓòÉ
  2580.  
  2581.  Window Enumeration 
  2582.  
  2583. The basis of tabbing is the ability to enumerate all of the children of a 
  2584. particular window.  The WinBeginEnumWindows() API will begin an enumeration. 
  2585. You provide it with the window whose children it is to enumerate.  It will 
  2586. return you a handle, which it uses to maintain an internal state table for the 
  2587. enumeration session.  Once you have an enumeration handle you can use 
  2588. WinGetNextWindow() to get each successive child window handle.  When done, you 
  2589. use WinEndEnumWindows() to close the enumeration handle.  WinGetNextWindow() 
  2590. will return a nul handle when it hits the end of the list. 
  2591.  
  2592. The Z-order of the child windows drives the iteration process.  In other words, 
  2593. the windows are enumerated in their defined Z- order.  This is why the order of 
  2594. creation of controls in the dialogs is important for the desired tabbing order, 
  2595. as you will see in the next section. 
  2596.  
  2597. Window enumeration is a fundamental type of magic that is behind many cool 
  2598. utilities that show you the hierarchical arrangements of any process' windows. 
  2599. You can use it to good effect sometimes, so check it out. 
  2600.  
  2601. Tabbing Enumeration 
  2602.  
  2603. Tabbing is accomplished via the WinEnumDlgItem() API.  This API is not magical 
  2604. in any way, and just builds upon the basic window enumeration system discussed 
  2605. above.  It effectively just enumerates the child controls of a particular 
  2606. window, queries their styles, and looks for WS_TABSTOP and WS_GROUP style bits 
  2607. to decide what to do.  It can answer questions like, "From the current focus 
  2608. window, what is the first/last control in the next/previous group" or "From 
  2609. this particular window, what is the next window that has the tabstop style" or 
  2610. "What is the next/previous window in the same group".  The tabstop and group 
  2611. styles really have no other use, so they are often not used when you create 
  2612. controls manually.  But, if you want to provide tabbing for manually created 
  2613. controls, you must apply them. 
  2614.  
  2615. As is often times the case in PM, the Dlg part of the name in WinEnumDlgItem() 
  2616. is a misnomer.  It is called that because that's all OS/2 itself uses it for. 
  2617. However, you can use it on your own frame windows, non-modal dialogs, or on the 
  2618. children of your client window, to easily provide tabbing without having to use 
  2619. dialog processing.  You always call it with a parent window whose children it 
  2620. is to enumerate, so there is no ambiguity about what window it is operating on. 
  2621.  
  2622. When a dialog is loaded, the loading code will create the controls in the order 
  2623. they are found in the dialog definition, giving each one HWND_BOTTOM as the 
  2624. z-order.  This effectively stacks the controls up in the same order as they 
  2625. were drawn by the dialog editor (or manually written by you into a dialog 
  2626. definition.)  When you want to provide tabbing for your own manually created 
  2627. controls, you just need to make sure to create them in the correct order and 
  2628. give them the desired tab stop and group styles, just as though you would have 
  2629. done them in a dialog editor. 
  2630.  
  2631. Doing It Yourself 
  2632.  
  2633. If you want to provide your own tabbing, I would suggest that you write a 
  2634. single function, say bDoTab() or something similar, that is just a wrapper 
  2635. around WinEnumDlgItem().  That way, in every application, you can just put a 
  2636. call to it in your client window's WM_CHAR message handling.  It will look at 
  2637. the character and see if it is a tab or arrow key or Alt-mnemonic character. If 
  2638. so, it will do the enumeration and move the focus to the new focus window, 
  2639. returning TRUE to say it handled the message.  The WM_CHAR code should then 
  2640. just return TRUE to say it was handled.  Otherwise, it returns FALSE and the 
  2641. WM_CHAR code should pass it on to the default handler or eat it or process it 
  2642. as needed.  The type of character (tab, back tab, up, down, left, right) 
  2643. controls the third parameter to WinEnumDlgItem().  This parameter is one of the 
  2644. EDI_xxxxx values, which tell WinEnumDlgItem() what kind of enumeration to do. 
  2645.  
  2646. To really work like dialogs do, you also need to check for mnemonics.  So, if 
  2647. the Alt key is pressed and the WM_CHAR message is a character message, you 
  2648. should enumerate the child windows and send each one a WM_MATCHMNEMONIC 
  2649. message.  If a control responds back saying that it matches the mnemonic 
  2650. character, put the focus on that control. 
  2651.  
  2652. If the character is an Enter key, then enumerate the children and send each one 
  2653. the WM_QUERYDLGCODE message.  This will cause the child window to return a set 
  2654. of DLGC_xxxx bit values.  You just need to look for one that has the 
  2655. DLGC_DEFAULT bit on and send it a BM_CLICK message.  This will cause that 
  2656. default button to send a WM_COMMAND message as though the user clicked on it. 
  2657.  
  2658. There are some more obscure features you might have to deal with to get exactly 
  2659. the same results as a dialog but those are the most common ones and should 
  2660. serve most apps.  And some of the dialog processing, as mentioned above, is not 
  2661. desirable for a normal window anyway.  Of course, if you are doing a class 
  2662. library, then the tabbing support should probably be implemented in the basic 
  2663. window class so that all windows can optionally provide tabbing for their 
  2664. children.  In my class library, the TWindow class has an 'autotab' attribute. 
  2665. If set, it calls its internal tabbing support wrapper function. This makes it 
  2666. trivial to provide tabbing any time its desired.  If the character input causes 
  2667. a tab operation, then the window is not even bothered by telling any input 
  2668. occurred so the support is transparent and automatic 
  2669.  
  2670. OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2671.  
  2672.  
  2673. ΓòÉΓòÉΓòÉ 8.4. Font Ids ΓòÉΓòÉΓòÉ
  2674.  
  2675.  Font Ids 
  2676.  
  2677. Font ids can cause no end of problems if they are not managed correctly. 
  2678. Unfortunately here as well there is just not sufficient documentation of the 
  2679. big picture.  Each process can have up to 255 logical font ids in existence at 
  2680. once.  Since font ids are associated with a presentation space, and most 
  2681. presentation spaces are cached and therefore have short lifetimes (usually just 
  2682. for a WM_PAINT), the maximum number of font ids is usually not an issue. Other 
  2683. applications, such as those which create persistent presentation spaces or more 
  2684. complex ones that have separately developed black box subsystems or that have 
  2685. multiple drawing threads, correct management of font ids is important. 
  2686.  
  2687. The simplest application is one that never uses any other font than the default 
  2688. system proportional font.  Such programs have no font id management issues 
  2689. because the 0th font id always magically exists.  For more complex software the 
  2690. two biggest problems with fonts are that multiple, separately developed, 
  2691. subsystems fight over the same ids and/or the leakage of font ids. The first 
  2692. will create weird problems because creation of logical fonts will fail (due to 
  2693. the id being in use by someone else) or logical fonts will be destroyed behind 
  2694. the back of someone who is using it.  The second will eventually bring the 
  2695. application to an eventual, often non-obvious demise. 
  2696.  
  2697. Font Id Management 
  2698.  
  2699. The first step in font management beyond just using the system proportional 
  2700. font is to define a set of global defines for the fonts to be used by the 
  2701. program.  If only one thread does all painting via cached presentation spaces, 
  2702. using font ids set up and then torn down all within the WM_PAINT code, then 
  2703. this scheme will work fine and all windows can share the same logical font ids 
  2704. without any conflict.  It's simple and easy to understand, as long as the 
  2705. program is simple. 
  2706.  
  2707. Once a program starts creating persistent presentation spaces, which can cause 
  2708. font ids to be in use outside of WM_PAINT code, or using multiple GUI threads, 
  2709. which can possibly have font ids in use simultaneously, the issue of font id 
  2710. management needs to be more formalized.  Though a program can certainly provide 
  2711. its own font id management system, there is one built into PM that works well 
  2712. enough.  You could though improve upon it if you felt it worth doing. 
  2713.  
  2714. The GpiQueryNumberSetIds() API will return the current number of font ids in 
  2715. use by the process (which are also used for custom patterns by the way, so this 
  2716. number may not just reflect fonts).  The GpiQuerySetIds() API will return 
  2717. information into 3 separate arrays (confusingly allocated as a single block of 
  2718. memory though) that tell you about the font ids in use by the process.  Using 
  2719. these two APIs, you can determine what ids are currently in use and, by 
  2720. extension, figure out one that is safe to use. 
  2721.  
  2722. ulGetNextId() 
  2723.  
  2724. The easiest way to use the PM font id management APIs is to write a 
  2725. function/method named, for instance, ulGetNextId().  It will find and return 
  2726. the next available id using the APIs mentioned above.  The only catch here is 
  2727. that, if you have multiple GUI threads or are writing general purpose code that 
  2728. might have to handle that situation, you must make the finding of a new id, and 
  2729. its being put into use, an atomic operation that is protected by a semaphore. 
  2730. The reason for this precaution is that GpiQuerySetIds() API doesn't care 
  2731. whether you've checked and found an id you liked.  It only knows which ones are 
  2732. in use.  If you use it to find an unused id, then another thread gets scheduled 
  2733. before you get the id into use and calls ulGetNextId(), it would get the same 
  2734. id.  One of them would later lose when trying to create a logical font with 
  2735. that id, causing errors from weird displays to outright crashes. 
  2736.  
  2737. So you really need another layer of code above the ulGetNextId() call.  You 
  2738. need to provide APIs that lock a common semaphore, get an id, create logical 
  2739. fonts or custom patterns, then release the semaphore.  This synchronization 
  2740. will insure that your management of font ids are thread safe.  In most 
  2741. programs, just the natural synchronization of PM's message passing architecture 
  2742. will insure that the semaphore is not actually ever needed.  But even in single 
  2743. threaded programs its just safer to do that small amount of work and never 
  2744. worry about it again. 
  2745.  
  2746. Of course, none of this helps if you must link to 3rd party code which chooses 
  2747. not to play with you.  It cannot know ahead of time what your locking scheme 
  2748. will be so you should assume (unless told otherwise) that it will probably use 
  2749. font ids (if at all) in the most optimistic manner, as discussed above.  If you 
  2750. are working from some common base library code it should definitely provide 
  2751. such an API for all to use. 
  2752.  
  2753. OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2754.  
  2755.  
  2756. ΓòÉΓòÉΓòÉ 8.5. PM Resources and Resource Ids ΓòÉΓòÉΓòÉ
  2757.  
  2758.  PM Resources and Resource Ids 
  2759.  
  2760. Some of the most obvious missing pieces of information in the OS/2 
  2761. documentation is related to the use of resources and resource ids, and the 
  2762. possible schemes for managing them.  Each OS/2 resource has a type (defined by 
  2763. the RT_xxxx values in BSEDOS.H) and an id.  When you watch the resource 
  2764. compiler putting out numbers like 3:100, that means a menu (RT_MENU is 3) with 
  2765. the id 100. 
  2766.  
  2767. The type and id values are used to extract the resource from a particular DLL 
  2768. or EXE module, using the DosGetResource() API.  You might never use 
  2769. DosGetResource() yourself, but that is the underlying API that extracts a 
  2770. resource into a system allocated memory buffer.  A program does not have to be 
  2771. a WINDOWAPI program to access resources in this way because the actual resource 
  2772. is not created, just the description of it is loaded. 
  2773.  
  2774. The Resource Id 'Name Space' 
  2775.  
  2776. Since you must access a resource by providing the module handle of the DLL or 
  2777. EXE module that it is attached to, there is effectively a 'resource name space' 
  2778. with three levels.  So a particular resource has a 'path' like this: 
  2779.  
  2780. \HModule\RT_xxxx\Id
  2781.  
  2782. This means, though it never seems to be pointed out, that the type:id pairs are 
  2783. automatically unique within each DLL or EXE module.  So, for instance, you can 
  2784. have a bitmap with an id of 1 in every single Dll in a program and there will 
  2785. be no problem with id conflict.  There can also be a bitmap and a string and a 
  2786. dialog with the id of 1 within a particular DLL or EXE.  This is particularly 
  2787. convenient ("Nay, absolutely required," he said in a regal manner), when 
  2788. building black box DLLs for distribution or doing large, multiple group 
  2789. development.  You just don't have to worry about resource id distribution 
  2790. except within a particular DLL or EXE module. 
  2791.  
  2792. Resource Access APIs 
  2793.  
  2794. You will generally access resources via a set of higher level (read PM 
  2795. oriented) APIs which themselves use DosGetResource() to load up the raw 
  2796. resource description.  These APIs then use that description to build the actual 
  2797. PM resource, after which they can discard the raw buffer. WinLoadString(), 
  2798. WinLoadDlg(), WinLoadPointer(), etc.  are examples of these convenience 
  2799. resource APIs.  You could easily (relatively speaking of course) replace these 
  2800. APIs with your own and enhance or expand on them, because they are not magical 
  2801. in any way and have no privileged knowledge or system access. The format of the 
  2802. raw buffer is, as far as I know, the exact format from the .RES file that was 
  2803. attached to the DLL or EXE.  Finding the details of that format for some of the 
  2804. resource types is though sometimes like drawing blood from a stone. 
  2805.  
  2806. For instance, in my class libraries, I wanted to have a strict separation 
  2807. between GUI and non-GUI code but wanted to have string resources accessible in 
  2808. the lowest level (kernel encapsulation) DLL.  So I provided my own methods to 
  2809. extract string resources.  Tehnically I could probably call WinLoadString() 
  2810. with a 0 HAB, but I did not want to cheat.  Its quite simple and you can do 
  2811. things like cache the most recently accessed strings for fast access (if that 
  2812. makes sense for your access patterns.)  String resources are actually grouped 
  2813. in sets of 16, called string tables, so you extract them in these tables and 
  2814. pull out the particular one of interest.  So caching this table is the most 
  2815. convenient way to keep them in memory.  This also makes it most efficient to 
  2816. group your strings (if they are not all just consecutively numbered) so that 
  2817. they start on ids which are multiples of 16. 
  2818.  
  2819. While I'm spending your development dollars here, another good use of this 
  2820. technique is in a scalable interface.  Lets say you wanted to provide a 4 level 
  2821. interface (from expert down to severely challenged, for me), you could arrange 
  2822. your string ids such that each 'message' started on a multiple of 16. But a 
  2823. 'mes sage' would actually be 4 strings at successive ids starting from the 
  2824. first one.  The program itself would just ask to load the 'message id' which 
  2825. would be the id of the first string in each group.  The loading function would 
  2826. pull in the string table for that 'message' and then use the program's current 
  2827. interface level to return the actual string for that level.  Having the base id 
  2828. for each message an even multiple of 16 insures that all of its related 
  2829. messages are in the same string table and loaded together. 
  2830.  
  2831. I also use DosGetResource() to load up dialog definition resource buffers and 
  2832. use that template to create my own dialog windows.  This gives me more control. 
  2833. See Dialogs As Main Windows above. 
  2834.  
  2835. OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2836.  
  2837.  
  2838. ΓòÉΓòÉΓòÉ 8.6. PresParams and System Colors ΓòÉΓòÉΓòÉ
  2839.  
  2840.  PresParams and System Colors 
  2841.  
  2842. Though they are relatively well covered in the documentation, presentation 
  2843. parameters and system colors (or at least their proper usage) are not well 
  2844. known.  Part of the problem is that their relationship to the standard 
  2845. controls, their relationship to each other, and how custom controls should use 
  2846. them in order to be good citizens is definitely not explained clearly enough. 
  2847.  
  2848. The Standard Controls 
  2849.  
  2850. The best way to see the intended use of presentation parameters (or presparams 
  2851. as they are called) and system colors is to look at how the standard PM 
  2852. controls use them.  A basic requirement of the standard controls (because of 
  2853. how widely they are used) is that they be configurable to the greatest degree 
  2854. practical.  An obviously important area of configurability for a control is 
  2855. that of the colors and fonts used in drawing itself.  So they all have a logic 
  2856. kind of like this: 
  2857.  
  2858.      For drawing my foobar, I will use presentation color X 
  2859.      If presentation color X is not present I will use system color Y 
  2860.  
  2861.  So, when you use the system color palette to set a system wide color (by 
  2862.  holding down Alt when you drag and drop a palette color), you are setting a 
  2863.  particular system color.  You can also do this via your own programs, so you 
  2864.  can create your own system palette manager if you desire.  There is nothing 
  2865.  magical about the system palette widget.  So every window which has not had 
  2866.  presentation color X explicitly set on it will use the new system color Y. In 
  2867.  order to make everyone update immediately, every window is sent a 
  2868.  WM_SYSCOLORCHANGE message and the screen is redrawn by invalidating all 
  2869.  windows. 
  2870.  
  2871.  In order to allow particular windows to buck the trend and have their own 
  2872.  color/font scheme (while still remaining user configurable), PM supports 
  2873.  presentation parameters.  PM supports a predefined set of presentation 
  2874.  parameters which are used by the standard controls (and user programs if they 
  2875.  care about presentation parameters at all.)  Dropping a color on a window 
  2876.  (without holding Alt) will cause the new presparam to be stored on the window 
  2877.  and a WM_PRESPARAMCHANGED message to be sent to it.  Its reaction will be 
  2878.  similar to the WM_SYSCOLORCHANGE discussed above.  Presentation colors/fonts 
  2879.  are set via the WinSetPresParam() API and queried via WinQueryPresParam(). 
  2880.  They can be removed via WinRemovePresParam().  The WinQueryPresParam() API 
  2881.  will automatically search up the ownership chain of the target window, if you 
  2882.  ask it to, searching for some ancestor window with that particular 
  2883.  presentation parameter.  I assume that this is intended to allow a single 
  2884.  owner window to control the appearance of its owned windows.  When a color or 
  2885.  font is dropped on a window, PM just calls WinSetPresParam() on that window. 
  2886.  
  2887.  The important things to remember here are that system colors only have to be 
  2888.  stored once for the whole system and that all windows call APIs, 
  2889.  WinQuerySysColor() in this case, to get their values.  Presentation parameters 
  2890.  are stored separately for each window on which they are set.  PM maintains 
  2891.  this storage for you and keeps each window's presparams associated with the 
  2892.  correct window handle. 
  2893.  
  2894.  Don't try to read any rhyme or reason into the names of the 
  2895.  system/presentation colors used by a window for a particular attribute of its 
  2896.  appearance.  There are a set of predefined, and pretty generically named, 
  2897.  colors.  In order to avoid massive proliferation of them, the standard 
  2898.  controls will just pick from that list ones with names that are hopefully 
  2899.  somewhat related to the purpose for which they are used (but sometimes 
  2900.  seemingly unrelated at all.)  The documentation on what standard controls use 
  2901.  what colors, is extremely pathetic.  So its only through the patient 
  2902.  experimentation of you and/or others that most of them get figured out.  If 
  2903.  you have IBM on-line documentation, open the PM Reference and search for 
  2904.  "Default Colors" to get about as much as you are likely to find.  And even 
  2905.  this documentation only says what they system/pres colors are, not what visual 
  2906.  aspect of the control they are used for. 
  2907.  
  2908.  Blending Into the Crowd 
  2909.  
  2910.  So, if you want to write a control window that acts like a standard control in 
  2911.  its use of colors and fonts, you must take a couple of steps.  The most 
  2912.  obvious is to write a wrapper function that takes a system color and a 
  2913.  presentation color.  It will first look for the presentation parameter and 
  2914.  return it if found, else it will query the system color and return that.  This 
  2915.  function then provides the basis for the paint logic's use of colors, while 
  2916.  moving lots of possibly replicated grunt code to one place. 
  2917.  
  2918.  You can take two approaches to the presentation colors and system colors your 
  2919.  window uses.  You can either just be very stateless and query them on every 
  2920.  paint, or you can cache them.  In the later scheme, you set them initially via 
  2921.  a manual query and thereafter update them on any WM_SYSCOLORCHANGE or 
  2922.  WM_PRESPARAMCHANGED message.  Your window class would just call, for instance, 
  2923.  a SaveColors() function initially upon creation and then upon receipt of 
  2924.  either message thereafter.  This would keep all of the code in the same place. 
  2925.  
  2926.  Custom Presentation Parameters 
  2927.  
  2928.  You can create your own presentation parameters by using values greater than 
  2929.  PP_USER.  The system will not send them to you of course since it doesn't know 
  2930.  them from Adam, but you can send them to your own windows.  If you set them on 
  2931.  'foreign' windows they will just be ignored (though PM will store them on the 
  2932.  window anyway) because those windows will not understand them.  Worse, they 
  2933.  might have defined their own custom params with the same id (and different 
  2934.  data layout) and freak out. 
  2935.  
  2936.  Saving/Reload Presentation Parameters 
  2937.  
  2938.  The WinStoreWindowPos() and WindowRestoreWindowPos() APIs will save and 
  2939.  restore the size, position, and presentation parameters of a window.  The 
  2940.  information is stored in the system INI file, so you have to provide the 
  2941.  application and key names to use.  These may or may not be very useful to you, 
  2942.  and the same functionality is pretty easy replicated on your own if these do 
  2943.  not do exactly what you want. 
  2944.  
  2945.  OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  2946.  
  2947.  
  2948. ΓòÉΓòÉΓòÉ 8.7. Subclassing and Superclassing ΓòÉΓòÉΓòÉ
  2949.  
  2950.  Subclassing and Superclassing 
  2951.  
  2952. PM provides two simple (though loose and not very formalized) mechanisms for 
  2953. inheritance with window classes, called subclassing and superclassing.  If I 
  2954. want to have a button that acts just slightly different than the standard push 
  2955. button, it makes more sense for me to try to just affect the behavior that I 
  2956. want to change and let the other functionality be handled as it was before. 
  2957. Actually, in this case, I could possibly make it a user-drawn button but that 
  2958. is a special case as it only affects visual behavior, and muddies the waters of 
  2959. this discussion for the moment so pretend it does not exist.  Let's say that I 
  2960. need a way to affect just the click of button 2 so that it pops up a help 
  2961. screen for that button, so really all I want to do is change what a button2 
  2962. click does. 
  2963.  
  2964. Subclassing 
  2965.  
  2966. Since almost all stimuli that affect a window come in the form of messages, if 
  2967. you can get the messages to come to you first, you can handle the ones you want 
  2968. and pass the others on to the original recipient, letting him/her handle them 
  2969. as before.  The simplest mechanism for doing this is to subclass the window, 
  2970. via the WinSubclassWindow() API.  You pass the window handle of the window you 
  2971. want to subclass, and a new window procedure.  PM makes your new window 
  2972. procedure the new recipient of all messages coming to that window.  It also 
  2973. returns to you the address of the previous window procedure, so you can pass 
  2974. any unneeded messages on to the original procedure.  Actually you have a number 
  2975. of options: 
  2976.  
  2977.      Handle the message and return without letting the original see it 
  2978.      Provide some preprocessing, then pass it onto the original 
  2979.      Let the original handle it first, then provide some post processing 
  2980.      Let it go straight to the original window procedure. 
  2981.  
  2982.  As far as I know, the window procedure to which a window's messages go is 
  2983.  always stored in the QWL_PFNWP window words, so most likely all 
  2984.  WinSubclassWindow() does is get the current value out, put the new one in, and 
  2985.  return the old one.  So you could easily do this operation yourself if you 
  2986.  chose to do so.  When a window is first created, this value is set by looking 
  2987.  up the window class passed to WinCreateWindow() and getting out the window 
  2988.  procedure given when the window class was registered via WinRegisterClass(). 
  2989.  
  2990.  Now we can provide the special processing for the button by trapping 
  2991.  WM_BUTTON2DOWN and WM_BUTTON2UP and doing our special processing on the up 
  2992.  event.  In this case we would not pass them on to the original since we don't 
  2993.  want it to take its default action of posting a WM_COMMAND to its owner. 
  2994.  
  2995.  Dialog windows are subclassed frames.  When you call WinLoadDlg() or 
  2996.  WinDlgBox(), you provide your dialog procedure address.  After WinLoadDlg() 
  2997.  (which is in turn called by WinDlgBox() if you call that) creates the frame 
  2998.  and the controls, it then calls WinSubclassWindow() on the frame using your 
  2999.  window procedure and saves the original frame procedure.  So messages first 
  3000.  come to your window procedure letting you deal with it.  If you pass it to 
  3001.  WinDefDlgProc() it will possibly handle it, in order to provide standard 
  3002.  dialog functionality such as tabbing, or pass it on to the original WC_FRAME 
  3003.  window procedure.  So the effect is of a layered set of 'virtual message 
  3004.  handlers' that cooperate in providing an extensible feature set, with each 
  3005.  layer taking one of the above 4 approaches to each message received. 
  3006.  
  3007.  Superclassing 
  3008.  
  3009.  Superclassing is less often done than subclassing because its advantages, 
  3010.  though sometimes significant, are often not needed enough to justify it.  The 
  3011.  best way to understand the differences between subclassing and superclassing 
  3012.  is to realize that subclassing is for applying per-window overriding of 
  3013.  messages.  In order words, subclassing is done on a per-window basis, after a 
  3014.  window has already been created.  The creator of the window usually decides 
  3015.  whether he/she wants to apply the subclass, not the window itself.  Another 
  3016.  disadvantage of subclassing is that, since the window must already exist in 
  3017.  order to subclass it, the WM_CREATE processing happens before the subclass can 
  3018.  be applied. 
  3019.  
  3020.  It would be nice to be able to extend, limit, or otherwise modify the 
  3021.  functionality of an existing window class such that it applied to all 
  3022.  instances of that window (without explicit action having to be taken by the 
  3023.  client code.)  Superclassing provides these benefits.  To superclass a window 
  3024.  you must follow these steps. 
  3025.  
  3026.      Query the class information of the class to super class 
  3027.  
  3028.      Store away the count of extra data words it has and the window procedure 
  3029.       of the class 
  3030.  
  3031.      Register a new window class, providing your own window procedure when you 
  3032.       register the class. 
  3033.  
  3034.      If your window class needs any extra window data beyond that of the 
  3035.       original class, add your needs to the original class' when you register 
  3036.       your new class.  One reason you might want to create extra window words 
  3037.       is to have a place to store per-window information without using the 
  3038.       QWL_USER area that the users of the new window class might need. 
  3039.  
  3040.  The important things to note here is that you have created a new window class. 
  3041.  So, when client code creates the window, it will provide your window class to 
  3042.  WinCreateWindow().  This has important ramifications to your control of the 
  3043.  situation.  They are: 
  3044.  
  3045.      Since the client is creating your window class, you will get the 
  3046.       WM_CREATE message.  Make sure that you pass it on to the underlying 
  3047.       window class first, to let it handle its initialization.  Then take care 
  3048.       of your own initialization needs. 
  3049.  
  3050.      You are in control of the situation.  You don't need to count on client 
  3051.       code to create a window of one class and then apply some subclass you 
  3052.       provide to it.  This means that the superclass will naturally apply to 
  3053.       all instances of the window, not just to selected instances of it. 
  3054.  
  3055.      You get to add more per-window instance data words, which is often 
  3056.       necessary.  You cannot use any existing window words because they could 
  3057.       all be used by the window class you superclassed (or by per-instance 
  3058.       subclasses applied by client code.)  By adding your storage needs to the 
  3059.       underlying class' your data is at indexes beyond those accessed by other 
  3060.       users of the window (because they don't know they even exist probably.) 
  3061.  
  3062.      You can tell at runtime whether a window is of your particular class 
  3063.       because you can query its class name or class info.  There is not an easy 
  3064.       way to tell if a subclassed window has had a particular subclass applied 
  3065.       to it. You cannot just compare its stored window procedure address with 
  3066.       your class' window procedure because it could have been subclassed as 
  3067.       well by client code. 
  3068.  
  3069.  Owner Draw 
  3070.  
  3071.  Some standard controls support an 'owner mode'.  This is not a subclass or 
  3072.  superclass because, in this case, the control is just letting its owner window 
  3073.  handle a particular aspect of its visual appearance.  Subclassing and 
  3074.  superclassing are applied to the control window itself and prevent the 
  3075.  parent/owner windows from having to be particularly aware of them once they 
  3076.  are set up. 
  3077.  
  3078.  OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3079.  
  3080.  
  3081. ΓòÉΓòÉΓòÉ 8.8. Transparent Windows ΓòÉΓòÉΓòÉ
  3082.  
  3083.  Transparent Windows 
  3084.  
  3085. Lots of people ask how a window like a combo box can cover a large part of the 
  3086. screen but only make use of the bottom part when it drops down the window. It 
  3087. does not affect the underlying windows any other time, letting you get straight 
  3088. to the windows underneath via mouse clicks.  And you can write a small program 
  3089. to check that the combo box is not changing its size when the drop down list is 
  3090. lowered.  It is that size all of the time, also obvious when you use the dialog 
  3091. editor to draw them. 
  3092.  
  3093. Effectively what is happening is that the combo box is selectively making parts 
  3094. of itself transparent visuall and to input.  Now everyone probably knows that 
  3095. its easy to make a window visual transparent by just not drawing anything 
  3096. during its painting events.  Usually they first find this out by accident and 
  3097. wonder why their window seems to be dragging around a bit of the desktop 
  3098. background.  But how do you make the window selectively transparent to mouse 
  3099. clicks? 
  3100.  
  3101. Hit Testing 
  3102.  
  3103. When it is time to dispatch a mouse event to a window, PM will send it a 
  3104. WM_HITTEST message.  The window can respond it one of four ways by returning 
  3105. one of the HT_xxxx values. 
  3106.  
  3107.      "Yes I'll take that mouse event", HT_NORMAL 
  3108.      "I'm transparent at that point so let it pass on to lower z- order 
  3109.       windows', HT_TRANSPARENT 
  3110.      "I can't take it but I'm not transparent either so don't pass it on", 
  3111.       HT_DISCARD 
  3112.      "Its an error for me to get a mouse event now", HT_ERROR 
  3113.  
  3114.  In the first instance, the event is passed on to the window.  In the second 
  3115.  case, WM_HITTEST is passed to the next control in the z-order chain that 
  3116.  contains the coordinate of the mouse event.  In the third case, the event is 
  3117.  just eaten.  In the last case, the window is brought to the foreground and PM 
  3118.  beeps at you, but the mouse event is otherwise eaten with no effect.  This is 
  3119.  how disabled windows can easily ignore mouse events but still get the required 
  3120.  button down effect of coming to the foreground. 
  3121.  
  3122.  From that explanation, it's probably pretty obvious now how a combo box does 
  3123.  its thing.  When it gets a WM_HITTEST, it checks whether the event is over a 
  3124.  part of itself that is not transparent.  If the list is dropped down, then 
  3125.  either the list box or entry field will get the message and just return 
  3126.  HT_NORMAL.  If the button hits the backing window, because the list box is not 
  3127.  covering it, it just returns HT_TRANSPARENT and the button goes on to the 
  3128.  window that is visible 'through' the combo box. 
  3129.  
  3130.  Handling Your Own Hit Testing 
  3131.  
  3132.  In your own window classes you likely never need to handle WM_HITTEST.  You 
  3133.  can just let it pass on to WinDefWindowProc(), which just returns HT_NORMAL to 
  3134.  let the mouse event come to the window or HT_ERROR if the window is disabled. 
  3135.  This is the correct behavior 99.99% of the time.  If you do need to handle it, 
  3136.  just use the passed mouse position to determine if your window is transparent 
  3137.  to mouse input there and return the appropriate hit test result.  This result 
  3138.  will be passed to the actual mouse event later, as one of the message 
  3139.  parameters (which is probably pretty universally ignored but its there.) 
  3140.  
  3141.  OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3142.  
  3143.  
  3144. ΓòÉΓòÉΓòÉ 8.9. Window Extra Data ΓòÉΓòÉΓòÉ
  3145.  
  3146.  Window Extra Data 
  3147.  
  3148. Under PM, since every window of a given window class shares the same window 
  3149. procedure, there must be a mechanism for each instance of a given window class 
  3150. be distinguishable.  This is accomplished by every window having a window 
  3151. handle which is passed to the window's procedure for each message received. 
  3152. Associated with each window handle is a small amount of extra data storage that 
  3153. is recreated for each instance of a window class.  Since this window data is 
  3154. associated with the window handle, the window procedure can be totally 
  3155. independent of which window is calling it.  The window procedure becomes a 
  3156. state machine and the window's extra is the state storage area, in which the 
  3157. window remembers its current state until the next message is received. 
  3158.  
  3159. Of course this whole argument applies to the less common use of window classes, 
  3160. which is to create a standard window type that can be used by many different 
  3161. subsystems or processes simultaneously.  Some PM programmers have only had need 
  3162. to create a window class for their own client windows or dialogs.  Since there 
  3163. is usually only one instance of these windows ever in existence, global 
  3164. variables might be used to track state information.  That is a valid approach 
  3165. in these cases, but PM makes it trivial to make even these windows inherently 
  3166. reentrant so that they can easily be instantiated multiple times in the future 
  3167. if needed. 
  3168.  
  3169. Just FYI, you can also use the same window procedure for multiple classes of 
  3170. window.  Often times, if I have multiple small dialogs in a single module, I 
  3171. will make one dialog procedure and use it for all of the dialogs.  The id of 
  3172. the dialog can be used, within each case of the switch statement used to 
  3173. process the individual messages, to determine the correct action to take.  So 
  3174. the dialog procedure is really a nested set of switch statements.  The outer 
  3175. one gets you to the correct message handling code.  Within the case for each 
  3176. handled message is a switch on the id of the dialog, which will usually call 
  3177. out to a function appropriate for each dialog.  Sometimes, if the code is 
  3178. trivial, it can just be done right there in the second switch.  This scheme can 
  3179. cut down on redundant code and keeping track with what dialogs use what dialog 
  3180. procedures, but it has its own set of possible gotchas. 
  3181.  
  3182. The extra window data of a window is accessed via a set of APIs named 
  3183. WinXXXWindowULong(), WinXXXWindowUShort(), and WinXXXWindowPtr(), where XXX is 
  3184. either Query or Set.  There is an extra WinSetWindowFlags() that sets bits in a 
  3185. 32 bit field of extra data.  There is not a WinQueryFlags() because 
  3186. WindowQueryULong() is fine for reading them.  There is a separate flag setting 
  3187. API because it provides a 'relevant bits' mask parameter which lets you 
  3188. indicate which actual bits you want to affect.  Otherwise, you would have to 
  3189. query the existing flag field, weave your changes in, then write them back. 
  3190. Instead you can do all that in one operation. 
  3191.  
  3192. When you call these APIs, you tell it the index of the memory field you want to 
  3193. access or set.  These indexes come in two forms, as is discussed next. But the 
  3194. bottom line is that the data is not just a flat memory buffer for you to access 
  3195. at will but a special area that must be accessed via an API. 
  3196.  
  3197. The Blessed Data, The Common Data 
  3198.  
  3199. There are two 'classes' of window data.  One set is defined by PM and its 
  3200. somewhat magical and the other is window data created by the outside world. In 
  3201. this case the outside world is any window class, including the built in window 
  3202. classes.  These magic window data fields are created automatically for every 
  3203. window so they are always available.  The data created by each window class for 
  3204. its windows can vary from window class to window class.  The amount of memory 
  3205. that a window class needs is indicated when the class is registered by 
  3206. WinRegisterClass(). 
  3207.  
  3208. The indexes for the magic window words are easily recognized in PMWin.H. They 
  3209. are the QWL_xxxx and QWS_xxxx values that have negative numbers.  All 
  3210. non-blessed window words have indexes of 0 or greater.  There are other window 
  3211. word indexes defined in PMWIN.H, for the frame window class for instance, but 
  3212. they are for window class data and have positive indexes. 
  3213.  
  3214. If you look at the indexes for the magic words and the ones for the frame 
  3215. window class, you will notice something interesting.  The window class specific 
  3216. data seems to be laid out as a single buffer, though I said it was not above. 
  3217. For instance, the QWL_xxx values each start at an index 4 bytes beyond the last 
  3218. one.  The fact is that the class specific data probably is a contiguous buffer, 
  3219. but you are not supposed to assume that because it might change.  The indexes 
  3220. of the magic words obviously have no relationship to the size of the values 
  3221. they point to.  They are just sequentially numbered negative numbers.  This 
  3222. probably implies that these values are just stored in various internal 
  3223. structures and the special indexes trigger the access APIs to go get them. 
  3224.  
  3225. Since the class specific data really is like a contiguous range of bytes that 
  3226. can be referenced at any offset, you can use WinQueryUShort() to query the low 
  3227. or high word of a field that is actually 32 bits just by adjusting the offset. 
  3228. This line would query the top two words of the QWL_USER field.  This would not 
  3229. work with the system defined values because they are not indexes in the same 
  3230. sense. 
  3231.  
  3232.      USHORT usVal = WinQueryWindowUShort(hwndMine, QWL_USER+2);
  3233.  
  3234. Ad Hoc Window Data 
  3235.  
  3236. It is important to note that most window data is 'class wide' meaning that is 
  3237. used in the same way by the window procedure for all instances of that window 
  3238. class.  But, for very general purpose windows such as the standard PM controls, 
  3239. there is very often a need for some storage that can be used in an ad hoc way 
  3240. by each individual instance of the window.  So, all of the standard controls 
  3241. provides a user definable area, QWL_USER, that can be used differently by each 
  3242. instance of the window, because it accessed by client code not by the window 
  3243. procedure.  If you write very general purpose window widgets, this is a good 
  3244. practice.  QWL_USER is defined as 0, so it is the first index in the class 
  3245. specific window words.  But you should probably not assume it will remain so 
  3246. defined.  If you create symbolic names for the indexes of your window words, 
  3247. you should technically do them as offsets from QWL_USER, such as QWL_USER+4. 
  3248. This way they will adjust automatically. 
  3249.  
  3250. The section on Subclassing and Superclassing above covered one way to extend 
  3251. the window storage of a predefined window class.  This is sometimes needed to 
  3252. allow extension of the class wide storage while still leaving the user 
  3253. definable storage area alone. 
  3254.  
  3255. Frame Window Words 
  3256.  
  3257. The frame window class has the most class defined storage words of any of the 
  3258. predefined controls, about 0x54 bytes or so it seems from perusing the headers. 
  3259. Partly this is because some of them are used when a frame is in 'dialog drag', 
  3260. and partly because the frame control has the most need to play magic tricks in 
  3261. the process of providing standard system functionality.  For instance, when a 
  3262. frame is activated, it will put the focus on the last of its descendant windows 
  3263. that had the focus.  This is accomplished by its storing the current focus 
  3264. window into QWL_HWNDFOCUSSAVE, when it gets a WM_ACTIVATE message indicating 
  3265. that it is being deactivated.  When the frame is minimized or maximize then 
  3266. restored, it goes back to its previous position.  It does this by saving away 
  3267. the current size and position in QWS_XRESTORE, QWS_YRESTORE, QWS_CXRESTORE, and 
  3268. QWS_CYRESTORE, when it receives a WM_ADJUSTWINDOWPOS message indicating that it 
  3269. is being minimized or maximized. QWL_FLAGS holds a set of bit flags that give 
  3270. lots of information about the current state of a frame window. 
  3271.  
  3272. Stupid Window Data Tricks 
  3273.  
  3274. You can often play nice tricks by knowing the content of the system defined or 
  3275. class defined window words and adjusting them as desired.  As discussed above 
  3276. in Changing Window Styles, you can sometimes extract the QWL_STYLES words, 
  3277. modify them, and put them back to change the styles of a window on the fly.  As 
  3278. far as I know, you can write a new value to QWS_ID to change the id a window 
  3279. (including to accidently setting it to the same id as another child, which can 
  3280. cause weirdness later.)  If you want to control the position to which a frame 
  3281. window will restore, then adjust the restore window words discussed in the 
  3282. previous section.  On restoration, the frame window will pull these values out 
  3283. and uses them to restore itself.  For a dialog, you can, as far as I know, 
  3284. reenter the dialog after WinDismissDlg() is issued (assuming you used 
  3285. WinLoadDlg()/WinProcessDlg() instead of WinDlgBox()) by clearing the 
  3286. FF_DLGDISMISSED flag and calling WinProcessDlg() again.  If you leave 
  3287. FF_DLGDISMISSED set and call it, it will probably just hide itself immediately 
  3288. because it will think it is already dismissed.  You can change the window to 
  3289. which focus will be put when the frame is activated by changing 
  3290. QWL_HWNDFOCUSSAVE.  Though I have not done it myself, I think you can adjust 
  3291. where the frame will minimize to the next time by adjusting the QWS_MINIMIZE 
  3292. and QWS_MAXIMIZE words.  I assume that, when the minimized frame is moved it 
  3293. updates these with the last place it was dropped (or maybe it just waits until 
  3294. its restored and does it then.) 
  3295.  
  3296. OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3297.  
  3298.  
  3299. ΓòÉΓòÉΓòÉ 8.10. Window Messages ΓòÉΓòÉΓòÉ
  3300.  
  3301.  Window Messages 
  3302.  
  3303. Window messages are pretty well explained in the documentation, however there 
  3304. are a few less understood issues surrounding them that I wanted to cover.  Of 
  3305. course the reason PM uses messages is that the system must dynamically link to 
  3306. code in the client's program, because it does not know ahead of time what 
  3307. windows the client code will use, how many of them, where their window 
  3308. procedures are, who will subclass them, etc.  So, instead of having a window 
  3309. provide virtual functions to call (like an object oriented system would), it 
  3310. allows each window class to provide one function pointer which it will call 
  3311. back when events occur.  Since it only allows one function, the message id is 
  3312. passed in order to allow multiple actions to be overloaded on this single 
  3313. function.  It's definitely not very type safe but allows a kind of flexibility 
  3314. that would otherwise not be very feasible for a procedural system. 
  3315.  
  3316. System Defined vs User Messages 
  3317.  
  3318. The system defines a number of messages, by defining a set of ids in the 
  3319. toolkit headers.  There is nothing to keep you from using these message ids for 
  3320. your own programs, but they will probably die a slow (or fast) painful death 
  3321. because the system will also continue to send them to you as well, passing the 
  3322. parameters that it says are correct for them.  This will certainly cause 
  3323. crashes.  You can, and will, sometimes fake system messages to your own windows 
  3324. but that is a special case and you must carefully emulate the parameter 
  3325. conventions of the system message you are faking. 
  3326.  
  3327. One common case is for WM_SIZE messages.  Many window procedures will have very 
  3328. special code that is run when it gets a WM_SIZE, which will calculate the sizes 
  3329. of its various parts and store them away.  However a window does not get sent a 
  3330. WM_SIZE message when it's first created; I assume because it is already told 
  3331. how big it was in the WM_CREATE.  Since the size code is in WM_SIZE, to avoid 
  3332. pulling the code out to a separate function, you can just have WM_CREATE send 
  3333. itself a WM_SIZE message to cause that code to correctly calculate everything 
  3334. for the initial size.  The initial window size is passed in the PCREATESTRUCT 
  3335. parameter of WM_CREATE. 
  3336.  
  3337. PM defines a value, WM_USER, above which all user messages must be placed. So 
  3338. you always define your own user defined messages as WM_USER+x, where x is some 
  3339. relative displacement value. 
  3340.  
  3341. Incoming/Outgoing 
  3342.  
  3343. One common area of misconception is that all windows in a program must have 
  3344. different user defined message or problems will occur because of 
  3345. misinterpreting a window message.  But this is only partly true, and is driven 
  3346. by the direction of the message.  All windows can define ids, for the messages 
  3347. that they want others to send to them, any way they want without worries of id 
  3348. clashes (because they are the only class of window which will receive them.) 
  3349. Sure there is the pathological problem of a window sending a message to the 
  3350. wrong window, but that is inherent in the looseness of such a message passing 
  3351. architecture.  The situation is not significantly improved by going through all 
  3352. the trouble of insuring unique incoming message ids. 
  3353.  
  3354. When messages are sent out from a window or subsystem to other windows, then 
  3355. the situation is different.  Since the sending window cannot know what incoming 
  3356. message ids are used by other windows, steps must be taken to insure 
  3357. uniqueness.  If the message is being sent out of some subsystem, a registration 
  3358. mechanism is often possible in which a client program registers what messages 
  3359. it wants sent to it.  I've used this a number of times.  In situations where 
  3360. messages must be transmitted to foreign process, third party, or otherwise 
  3361. uncontrolled windows for which the registration mechanism might not be 
  3362. feasible, the only solution is often to create a system atom.  The system atom 
  3363. table is a mechanism for creating guaranteed unique values within the system. 
  3364. This atom can them be used to create a unique outgoing message id. 
  3365.  
  3366. The catch of using atoms is that they are no longer compile time constants and 
  3367. therefore cannot be used as cases in the usual window procedure switch 
  3368. statement.  So you either have to check for them in default case of the switch 
  3369. or via a set of if-then- elseif blocks prior to entering the main switch 
  3370. statement.  And, of course, the parties involved must agree on the atom by 
  3371. either passing it along or having a common atom name which they can all look up 
  3372. on startup.  Window Relationships 
  3373.  
  3374. I guess that the writers of most OS/2 documentation assume that the 
  3375. relationships of windows to one another are so obvious that they don't need to 
  3376. say the obvious things about them.  But, there are a couple of often 
  3377. misunderstood issues surrounding window relationships. 
  3378.  
  3379. Basically there are two defined relationships between windows, parentage and 
  3380. ownership.  However, these two relationships are not on the same level at all. 
  3381. Of the two parentage is the one that is most important and 'built into' PM. 
  3382. Ownership is more of an artificial relationship that was created to deal with a 
  3383. common GUI problem. 
  3384.  
  3385. OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3386.  
  3387.  
  3388. ΓòÉΓòÉΓòÉ 8.11. Window Parentage ΓòÉΓòÉΓòÉ
  3389.  
  3390.  Window Parentage 
  3391.  
  3392. Every window in PM except for the magical desktop (HWND_DESKTOP) and object 
  3393. (WM_OBJECT) windows have parent windows.  This is a required relationship that 
  3394. always exists, though the parent of a window may be changed as desired. 
  3395. Parenthood implies these facts: 
  3396.  
  3397.      All windows are placed relative to their parent window.  When you query 
  3398.       or set a window's position, that position is relative to the lower left 
  3399.       corner of its parent window. 
  3400.  
  3401.      Since windows cannot exist without a parent, they are destroyed when 
  3402.       their parent is destroyed.  This is both a convenience and a necessity. 
  3403.  
  3404.      When a window gets a WM_DESTROY, its child windows still exist so that 
  3405.       they can be queried, their size/position saved, etc.... 
  3406.  
  3407.      When a window gets its WM_CREATE message it cannot have any child windows 
  3408.       because no one could have created any yet (other than PM itself who 
  3409.       won't). The window handle is not returned from WinCreateWindow() until 
  3410.       WM_CREATE processing is completed, so no one has had access to the window 
  3411.       in order to create a child window for it or assign one to it. 
  3412.  
  3413.      Child windows will never show outside of their parent windows because 
  3414.       they clipped to it.  This is a natural effect of PM and does not require 
  3415.       any special effort on your part. 
  3416.  
  3417.      WinQueryWindow(hwndChild, QW_PARENT) cannot fail if hwndChild is a valid 
  3418.       window because it must have a parent to exist.  There might be some 
  3419.       pathological multi-threaded situation where the query is made while the 
  3420.       switch is occurring. 
  3421.  
  3422.  Parenthood of a window can be changed using the WinSetParent() API.  This API 
  3423.  is used often by PM to control, for instance, menus which often must appear 
  3424.  and disappear on demand.  Instead of rebuilding them every time, their parent 
  3425.  is set to HWND_OBJECT, which hides them without affecting their size/position 
  3426.  information.  You can use this scheme yourself to say display one of a set of 
  3427.  windows in a particular area of your client screen according to some 
  3428.  circumstance.  Be aware that, when you do this, those windows will not be 
  3429.  destroyed automatically when your client is destroyed now because automatic 
  3430.  destruction only occurs for child windows.  So you must generally track them 
  3431.  by window handle so you can destroy them when you get a WM_DESTROY message. 
  3432.  You cannot use ids to find them because any process can have windows under 
  3433.  HWND_OBJECT, some of which could have your same id.  Another exception to this 
  3434.  rule is that frame windows will destroy all of their child windows (naturally 
  3435.  like everyone else does) plus all of their owned windows.  This makes sure it 
  3436.  gets all of those windows cleaned up successfully. 
  3437.  
  3438.  Window Ownership 
  3439.  
  3440.  Whereas window parentage is a somewhat 'physical' relationship, ownership is 
  3441.  more of a 'legal' relationship.  In PM, when a user interacts with a control 
  3442.  window, that window will send a WM_CONTROL message to its owner window.  In an 
  3443.  object oriented system, this would have probably worked the other way where 
  3444.  control windows would handle their own events in an extendable way via 
  3445.  polymorphism; but, in a non-OOPs system, the most practical way to provide 
  3446.  extensibility of the standard controls is to let the client code respond on 
  3447.  their behalf as suits the application's particular circumstances. Given that, 
  3448.  there arose the need to know 'who' was interested in these events. Therefore 
  3449.  an artificial relationship of ownership was invented, so that a 'legal 
  3450.  contract of notification' could be arranged between two windows. Ownership is 
  3451.  not affected by the parenthood heirarchy at all, so a window's owner could 
  3452.  possibly be almost any other window. 
  3453.  
  3454.  Since this relationship is more artificial, it can be ignored totally (i.e. a 
  3455.  window is not required to have an owner) and it can be used by custom window 
  3456.  classes to represent some other type of legal contract.  The (almost) only 
  3457.  reason it is magical at all is because WinQueryWindow() allows a window's 
  3458.  owner to be queried.  But you could easily arrange to provide other 
  3459.  relationships between your own windows if you wish to do so.  It would be more 
  3460.  work than ownership because you would have to provide your own internal 
  3461.  mapping tables or store a reference to the other window inside each window. 
  3462.  But it would be just as 'legitimate' a relationship as ownership. 
  3463.  
  3464.  Ownership can be changed or set via the WinSetOwner().  It can be set to 0, to 
  3465.  make the window no longer have an owner.  This might be a convenient way to 
  3466.  make child controls 'shut up' for extended periods of time when the owner is 
  3467.  not prepared to deal with them. 
  3468.  
  3469.  Note that the ownership relationship is used (just for confusion's sake) for a 
  3470.  couple things other than the event notification.  Presentation parameters can 
  3471.  be inherited via the ownership chain and frame windows have an option to be 
  3472.  moved relative to their owner.  This allows them to float outside their parent 
  3473.  but maintain the same position relative to it.  Also, frame windows minimize 
  3474.  their owned windows when they are minimized and destroy their owned windows 
  3475.  when they are destroyed, which is unlike any other window class. 
  3476.  
  3477.  OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3478.  
  3479.  
  3480. ΓòÉΓòÉΓòÉ 8.12. Summary ΓòÉΓòÉΓòÉ
  3481.  
  3482.  Summary 
  3483.  
  3484. I hope this quick tour of OS/2's rougher surfaces has helped some.  I realize 
  3485. that this article jumps around somewhat erratically and that most of these 
  3486. subjects could each be extended to fill a full book chapter in order to cover 
  3487. all of their details.  But this overview should hopefully give you a leg up on 
  3488. some of the problem areas and some potential areas of improvement in your code. 
  3489. And besides, I would not have any time to actually write any code and would 
  3490. have nothing to write about next time.  Hopefully I will be able to expand upon 
  3491. some of these topics in subsequent issues. 
  3492.  
  3493. If you have any questions or need amplication of any of these issues feel free 
  3494. to drop me a line to droddey@jaguNet.com or, on Compuserve, at id 72170,1614. 
  3495. Have fun with PM, but don't put your eye out with that thing!! 
  3496.  
  3497. OS/2 Frequently Asked Questions - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3498.  
  3499.  
  3500. ΓòÉΓòÉΓòÉ 9. /dev/EDM2/BookReview ΓòÉΓòÉΓòÉ
  3501.  
  3502. /dev/edm2/BookReview 
  3503.  
  3504. Written by Carsten Whimster 
  3505.  
  3506. Introduction 
  3507.  
  3508. In /dev/EDM2/BookReview, I focus on development books and materials. I have 
  3509. written this column from the point of view of an intermediate PM C programmer 
  3510. and intermediate REXX programmer. Pick up whichever book strikes your fancy, 
  3511. and join the growing group of people following our PM programming columns. I 
  3512. have already reviewed a number of beginner's books, and will try to concentrate 
  3513. a bit more on intermediate techniques and special topics from now on. 
  3514.  
  3515. Please send me your comments and thoughts so that I can make this column as 
  3516. good as possible. I read and respond to all mail. 
  3517.  
  3518. The OS/2 Certification Handbook is a book that is designed to prepare you for 
  3519. the OS/2 Certified Engineer tests. 
  3520.  
  3521. /dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3522.  
  3523.  
  3524. ΓòÉΓòÉΓòÉ 9.1. Errata ΓòÉΓòÉΓòÉ
  3525.  
  3526. Errata 
  3527.  
  3528. My Web page is still growing, and has recently had over 2700 hits. Perhaps my 
  3529. joke about using 5 digits for my hit-counter is not a joke after all. At this 
  3530. pace, it may hit 10000 by Christmas. Luckily, I won't need 6 digits for a 
  3531. while. Check it out at <URL:http://www.undergrad.math.uwaterloo.ca/~bcrwhims/>. 
  3532.  
  3533. <plug warning> My POV-Panel/2 has recently gone golden, and the release is 
  3534. called 1.1a and is available on my web page, as well as on ftp.cdrom.com, and 
  3535. hobbes.nmsu.edu. Once I started getting registrations, I realized that I was 
  3536. not terribly well qualified to answer complicated questions about why my 
  3537. program wasn't working on certain real-world setups, and so I looked into this. 
  3538. This culminated in the purchase ($$$) of this month's book. If you are 
  3539. interested in ray-tracing, use POV-Ray, and sometimes write your own scripts, 
  3540. you definitely want to take a look at this program. </plug warning> 
  3541.  
  3542. Partition Magic from Power Quest has to be one of the most timely programs to 
  3543. ever be released. I have just assisted several friends in installing OS/2, and 
  3544. in each case I am not sure if they would have installed it if they had not been 
  3545. able to move partitions around, grow them, shrink them, and convert them. This 
  3546. may be one of OS/2's strongest points. It is now available in a DOS/Windows 
  3547. version too, but it was originally an OS/2 program. Partition Magic definitely 
  3548. makes it easier to try OS/2 without nuking your current setup, which may be 
  3549. enough to convince more people to switch. Of course, when the next release of 
  3550. your favorite C/C++ compiler is released, you may well find that your 
  3551. development partition is too small to hold it. What better time to get a new 
  3552. harddrive, and resize partitions <grin> 
  3553.  
  3554. /dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3555.  
  3556.  
  3557. ΓòÉΓòÉΓòÉ 9.2. OS/2 Certification Handbook ΓòÉΓòÉΓòÉ
  3558.  
  3559. OS/2 Certification Handbook 
  3560.  
  3561. OS/2 Certification Handbook may seem like an odd fit for these pages. The 
  3562. reason that I am reviewing it is that I needed some of the information in it to 
  3563. properly support my shareware program. I was getting strange questions, the 
  3564. answers for which I had never come across, and it quickly became apparent that 
  3565. I needed a more authoritative command of all things OS/2. Hence the purchase 
  3566. (and quite a hefty one at that) of this book. The way I see it, most shareware 
  3567. authors, of which I am sure we have quite a few as readers, could use this 
  3568. information to support their products. Here are the chapter titles: 
  3569.  
  3570.    Part One: Installation
  3571. 1. Versions of OS/2
  3572. 2. Planning for Installation
  3573. 3. Installing OS/2 Warp, Version 3
  3574. 4. Installing OS/2 2.1
  3575. 5. Advanced Installation Tips
  3576. 6. Printer Installation
  3577. 7. Font Installation
  3578. 8. Control Files
  3579. 9. Installing and Migrating Applications
  3580.    Part Two: Using OS/2
  3581. 10. Understanding OS/2 Concepts
  3582. 11. Performing Basic Operations
  3583. 12. Manipulating Windows
  3584. 13. Getting Online Information
  3585. 14. Using Desktop Objects
  3586. 15. Using Menus and Notebooks
  3587. 16. Using Advanced WPS Features
  3588. 17. Understanding the File System
  3589. 18. Running Applications
  3590. 19. Installing Applications
  3591. 20. System Startup
  3592. 21. Printing
  3593. 22. Customizing OS/2
  3594. 23. Using the Workplace Shell Efficiently
  3595.    Part Three: Supporting OS/2
  3596. 24. Support Tools
  3597. 25. Software Aids
  3598. 26. The Boot Process
  3599. 27. Solving Video Problems
  3600. 28. Solving Printer Problems
  3601. 29. CONFIG.SYS
  3602. 30. Error Recovery
  3603. 31. System Dumps
  3604.    Part Four: OS/2 Performance and Tuning
  3605. 32. Understanding OS/2 Memory and Task Architecture
  3606. 33. Measuring Performance
  3607. 34. Maximizing Performance
  3608. 35. Understanding Other Performance Issues
  3609.    Part Five: Appendixes
  3610. A. Using the Keyboard
  3611. B. Help via Modem and Fax
  3612. C. Maintenance
  3613. D. Understanding REXX
  3614.    Part Six: Command Reference
  3615. Command Reference
  3616.  
  3617. Again this month, I will concentrate on the sections, rather than the chapters, 
  3618. since the divisions between the chapters are less important than in programming 
  3619. books. In addition, this book is absolutely immense, and reviewing it in any 
  3620. kind of detail in one month is impossible. 
  3621.  
  3622. Part One covers various installation issues, including new features in Warp, a 
  3623. planning section for installation, which includes checking out the system 
  3624. requirements for the intended usage versus the actual requirements available, a 
  3625. detailed section on configuration decisions, such as whether or not to use 
  3626. HPFS, how to arrange partitions, and whether or not to use Boot Manager. This 
  3627. is followed by a small section that outlines what DOS and Windows programs OS/2 
  3628. can support, and how. Finally in chapter two there is a brief run-through of 
  3629. the amount of space required for the various selectable components, and when it 
  3630. makes sense to leave out components. At the end of every chapter there is a 
  3631. small questionnaire which tests how well you have read and retained the 
  3632. information offered in that chapter. This is not always as easy as it sounds! 
  3633.  
  3634. Chapters three and four describe the actual installation in detail, for Warp 
  3635. and OS/2 2.1, respectively. Both the easy installation and the advanced 
  3636. installation options are covered for Warp. Installing OS/2 2.1 (for those of us 
  3637. that remember) is actually nearly identical to installing Warp, except that it 
  3638. has gotten easier, and there are now a few more options along the way, and a 
  3639. lot more drivers. Advanced installation topics are the subject of chapter five. 
  3640. Oddly enough, the first sentence reads "Wrapping up the installation section of 
  3641. this book, this chapter covers...". Considering that the installation section 
  3642. covers chapters one through nine, this statement is a little premature. 
  3643. Occasionally, I get the distinct impression that this book is a changed version 
  3644. of an earlier book, although I don't know which. Understanding OS/2's directory 
  3645. structure, support options, and removing OS/2 is all explained here. There is 
  3646. another small error in the support section. The newsgroups on the Internet are 
  3647. claimed to start with comp.os2 whereas they in fact all start with the 
  3648. comp.os.os2 prefix. 
  3649.  
  3650. The next chapter discusses printer considerations. This includes a discussion 
  3651. of the flow through the system of the print job, printing in DOS, printing in 
  3652. WIN-OS/2, pooling, spooling, and installation. Chapter 7 deals with fonts. It 
  3653. starts with a section describing the terminology of fonts, and continues 
  3654. through installation, and fonts in WIN-OS/2. Chapter eight covers "control 
  3655. files". This includes the obvious INI files, the CONFIG.SYS, and STARTUP.CMD, 
  3656. but covers everything only in light detail. These topics will be revisited in 
  3657. another section. Finally, chapter nine covers installing and migrating 
  3658. applications. A brief tour through the various memory types and requirements, 
  3659. video support for DOS and Windows, and VDM settings ends up in installing and 
  3660. migrating the applications, and creating program objects for them. Modifying 
  3661. the migration database is also covered. 
  3662.  
  3663. The second part, called "Using OS/2," is a fair amount larger, and I will not 
  3664. mention the chapters explicitly, but rather cover only the topics of most 
  3665. interest to us, as OS/2 professionals. This section discusses objects and the 
  3666. WPS. It enforces a rigid understanding of the object paradigm, including both 
  3667. how to set them up, and how to manipulate them. Getting help on the use of 
  3668. certain objects is covered, the settings notebooks are explained, customization 
  3669. of objects, the file system's relationship to objects, and printing and objects 
  3670. are all explained. The various object types are covered early on. The various 
  3671. window components are explained, but this should be old hat to most OS/2 
  3672. programmers. Most of the stuff covered is done so in excruciating detail, but 
  3673. every once in a while, there is a little gem of information which you didn't 
  3674. know before, and which clears up something that happened once in the past. At 
  3675. other times there is very little on some subject. The new feature "pickup" is 
  3676. explained. Here is a feature which is potentially quite useful, but which I bet 
  3677. very few people actually use. DDE between applications is also touched on. 
  3678. Sometimes it is surprising how little detail there is on some subject or other. 
  3679. Considering the thickness of the book, it may seem a little odd, but when you 
  3680. check, there is actually something written on every page, and so I guess they 
  3681. must have run out of room for certain minor things. Chapter 23 is one of the 
  3682. more interesting chapters. Entitled "Using the Workplace Shell Efficiently", it 
  3683. has a definite emphasis on contrasting various features for the purpose of 
  3684. enabling you to choose the one you prefer. Again, this chapter seems a little 
  3685. short on explanations. 
  3686.  
  3687. Part three is the one of most interest to me personally, and is in fact the 
  3688. part that I bought the book for. "Supporting OS/2" is of immediate importance 
  3689. to any shareware or commercial OS/2 programmer. How many times have we heard 
  3690. "it doesn't work on my system", and then had to (sometimes remotely) analyze a 
  3691. system only to find out that a certain option, or replacement program isn't 
  3692. 100% compatible. 4OS2 falls into this latter category for me. Great program, 
  3693. but careful how you use it. It doesn't have a "start" command, for example, so 
  3694. don't make it your default shell unless you know that you don't need this 
  3695. feature. I had trouble with this in my POV-Panel/2. It uses the "start" command 
  3696. to launch POV-Ray. The resulting error took me a month to figure out! In the 
  3697. future, I want to be better at this type of thing, hence this book. 
  3698.  
  3699. First, the various types of built-in documentation are explained. Besides this, 
  3700. there are several files and tools mentioned which are available through IBM's 
  3701. BBSes. How would you find out about these tools without this book, without 
  3702. spending tons of time browsing the net, trying out tools and programs? I don't 
  3703. know. Yet this is how they recommend that we proceed. So be it. Some tools are 
  3704. outlined next. The boot process is explained in a little more detail than 
  3705. usual, including the POST, BIOS/CMOS, and OS/2 itself. Video problems are next, 
  3706. followed by printer problems. Following this is an immensely helpful chapter on 
  3707. the CONFIG.SYS, including what many of the parameters mean, and what they do. 
  3708. The actual tuning comes later, but this chapter really helps the comprehension 
  3709. of this text-based dinosaur fragment in OS/2. The following chapter is also a 
  3710. great help, but in a different way. It treats recovery from terrible events, 
  3711. and how to prepare. It includes brief explanations of some of the tools, such 
  3712. as tedit, bootos2, and other EWS programs. Diagnosing is another useful 
  3713. sub-heading of this chapter. The level of detail isn't great, though. System 
  3714. dumps is an OS/2 feature I have never used. Actually, I did do a dump once, but 
  3715. then I had no tools to analyze the dump, so I deleted it. Chapter thirty-one 
  3716. discusses dumps briefly. 
  3717.  
  3718. Part four is about performance and tuning, and I am sure that there is no area 
  3719. of OS/2 which involves more black magic than this. Everyone seems to have their 
  3720. own opinion of what works best, so it is refreshing to have official advice. 
  3721. What is more important than just making changes, this section explains how to 
  3722. measure performance differences, and thus effectively lets anyone try anything 
  3723. they want, without fear that they have inadvertently slowed down their system 
  3724. without knowing it. For us OS/2 professionals (you are going to get very tired 
  3725. of me saying that <grin>), there is a certain pride, but also practical value, 
  3726. in having a well-tuned system. Everything from the CPU to multi-tasking and 
  3727. applications is discussed. Many OS/2 features which are used by programmers are 
  3728. discussed, such as semaphores, signals, pipes and so on. Inherent features of 
  3729. the O/S itself, such as virtual memory, I/O, and file systems are also 
  3730. discussed. All of this is followed by practical ways of measuring performance. 
  3731. This includes using "pulse", SPM/2 (available from IBM),  and creating your own 
  3732. tool. Both installation-time options and post-installation options are 
  3733. examined. There is probably more meat on the why's of OS/2 in this section than 
  3734. in any other single place, possible excluding OS/2 Warp Unleashed, and The 
  3735. Design of OS/2. 
  3736.  
  3737. The final part consists of appendixes (appendices?) only. The REXX appendix is 
  3738. quite informative, and includes a mini-reference, but it is a bit short. The 
  3739. other three chapters are even shorter. The book is wrapped up with a command 
  3740. reference, and a good index. 
  3741.  
  3742. /dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3743.  
  3744.  
  3745. ΓòÉΓòÉΓòÉ 9.3. Summary ΓòÉΓòÉΓòÉ
  3746.  
  3747. Summary 
  3748.  
  3749. This book is not a programmer's book, but it is a book for the aspiring 
  3750. self-employed software company CEO <grin>. It teaches long and hard lessons 
  3751. about the intricate details of OS/2, both OS/2 2.1 and Warp. Installing, using, 
  3752. and supporting OS/2 are all taught well, and apart from a few unfortunate 
  3753. errors, it is all quite accurate. For any reasonably well-versed OS/2 user, 
  3754. between 50 and 75 percent of the material will not be new, but the remaining 25 
  3755. to 50 percent would be very hard to learn on your own. It is a very expensive 
  3756. book, but it is very large (over 1000 pages) and well worth it. I rate this 
  3757. book an A-, due to the errors and occasional omissions. 
  3758.  
  3759. /dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3760.  
  3761.  
  3762. ΓòÉΓòÉΓòÉ 9.4. Book Reviewed ΓòÉΓòÉΓòÉ
  3763.  
  3764. Book Reviewed 
  3765.  
  3766. OS/2 Certification Handbook, Hallberg and Ivens 
  3767.  - New Riders Publishing. ISBN 1-562-05407-4. US$89.99, CAN$122.95 
  3768.  - OS/2 Professionals 
  3769.  - A- 
  3770. This certification primer is full of information, much of it trivial, much of 
  3771. it worth its weight in gold. It comes with a CD including sample tests. This 
  3772. book is recommended to OS/2 programmers who like to think of themselves as more 
  3773. well-rounded OS/2 professionals, rather than just coders, and anyone thinking 
  3774. of taking a crack at programming and supporting OS/2 for a living. You could 
  3775. follow up the book with the OS/2 Certified Engineer tests, but this is not 
  3776. necessary. 
  3777.  
  3778. NOTES 
  3779.  
  3780. Please note that books aimed at different audiences should only be compared 
  3781. with great care, if at all. I intend to concentrate on the strong points of the 
  3782. books I review, but I will point out any weaknesses in a constructive manner. 
  3783.  
  3784. LEGEND 
  3785.  
  3786. BOOK: The name of the book, and the author(s) 
  3787.  
  3788. PUBLISHING INFORMATION: Publishing company, ISBN, and approximate price. 
  3789.  
  3790. AUDIENCE: This is a description of the audience I think the book targets best. 
  3791. This is not intended as gospel, just a guideline for people not familiar with 
  3792. the book. 
  3793.  
  3794. MARK: My opinion of the success of the book's presentation, and how well it 
  3795. targets its audience. Technical content, accuracy, organization, readability, 
  3796. and quality of index all weigh heavily here, but the single most important item 
  3797. is how well the book covers what it says it covers. Many books try to cover too 
  3798. much, and get a lower mark as a result. 
  3799.  
  3800. A+  Ground-breaking, all-around outstanding book
  3801. A   Excellent book. This is what I want to see happen a lot
  3802. A-  Excellent book with minor flaws
  3803. B+  Very good book with minor flaws or omissions
  3804. B   Good book with some flaws and omissions
  3805. B-  Good book, but in need of improvement
  3806. C+  Mediocre book with some potential, but in need of some updating
  3807. C   Mediocre book with some good sections, but badly in need of fixing
  3808. C-  Mediocre book, little good material, desperately in need of an overhaul
  3809. D   Don't buy this book unless you need it, and nothing else exists
  3810. F   Don't buy this book. Period
  3811.  
  3812. COMMENTS: This is a very brief summary of the review proper. 
  3813.  
  3814. /dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3815.  
  3816.  
  3817. ΓòÉΓòÉΓòÉ 9.5. Index ΓòÉΓòÉΓòÉ
  3818.  
  3819. Index 
  3820.  
  3821. This Content Index is designed to let you find the book that covers the topics 
  3822. you need to learn about. It will eventually have a lot of categories, with each 
  3823. book being rated along each row. These tables will be quite large, and will 
  3824. continually grow, so please give me your feedback regarding what categories you 
  3825. would like to see, and which you don't. It may take me a while to flesh them 
  3826. out, so have a little patience. 
  3827.  
  3828. BOOK LEGEND: 
  3829.  
  3830. code issue title
  3831.  
  3832. RWP  2-3   Real World Programming for OS/2 2.1
  3833. LPE  2-4   Learning to Program OS/2 2.0 Presentation Manager by Example
  3834. ODD  2-5   Writing OS/2 2.1 Device Drivers in C
  3835. GPI  2-6   OS/2 Presentation Manager GPI
  3836. TAO  2-7   The Art of OS/2 2.1 C Programming
  3837. MOR  2-8   Mastering OS/2 REXX
  3838. RSH  2-9   REXX Reference Summary Handbook
  3839. ADO  2-10  Application Development Using OS/2 REXX
  3840. PMP  2-11  OS/2 Presentation Manager Programming
  3841. DOA  3-1   Designing OS/2 Applications
  3842. OSP  3-2   OS/2 Programming
  3843. TGO  3-4   The GUI-OOUI War
  3844. OU   3-5   OS/2 Warp Unleashed, Deluxe Edition
  3845. QR1  3-6   WIN Functions, OS/2 Quick Reference Library Volume 1
  3846. PWG  3-7   Programming the OS/2 Warp Version 3 GPI
  3847. DHP  3-8   Designing High-Powered OS/2 Warp Applications
  3848. OCH  3-9   OS/2 Certification Handbook
  3849.  
  3850. NOTE: Books which cover the same material can look similar in this table, but 
  3851. be different in real life. The style of a book, for example, can not be seen 
  3852. from a quick table, so make sure that you follow up by reading the reviews of 
  3853. the books you find here. Finally, be sure that the books you are comparing are 
  3854. aimed at the same audiences. 
  3855.  
  3856. PM C BOOKS: 
  3857.  
  3858. BOOK MARK Kernel Device VIO/ PM   GPI Fonts Print
  3859.            Basics Driver AVIO
  3860.  
  3861. RWP   B+    2       0     0    4    4   4      3
  3862. PME   B-    1       0     0    2    2   2      0
  3863. ODD   A     0       5     0    0    1   0      1
  3864. GPI   C+    0       0     0    0    5   2      3
  3865. TAO   B+    3       2     1    4    1   2      0
  3866. PMP   A-    1       0     1    5    3   4      2
  3867. OSP   B+    2       0     0    3    2   1      0
  3868. QR1   A     0       0     0  5(WIN) 0   0      0
  3869. PWG   A-    0       0     0    1    5   5      5
  3870.  
  3871. REXX BOOKS: 
  3872.  
  3873. BOOK MARK REXX     WPS    Reference
  3874.            Intro
  3875.  
  3876. MOR   B    4         0         2
  3877. RSH   A    1         2         5
  3878. ADO   A-   3         2         4
  3879.  
  3880. SYSTEM AND NON-PROGRAMMING BOOKS: 
  3881.  
  3882. BOOK MARK Kernel Device  VIO/   PM  Thread  GPI  Fonts  Print  WPS
  3883.            Basics Drivers AVIO
  3884.  
  3885. DOA   A     4        4     2     4     5     3      2     3     1
  3886. TGO   B     0        0     0     2     1     0      2     1     5
  3887. OU    A+    1        4     4     5     2     5      5     5     5
  3888. DHP   A     4        4     2     4     5     3      2     3     1
  3889. OCH   A-    ?        ?     ?     ?     ?     ?      ?     ?     ?
  3890.  
  3891. RATINGS LEGEND:
  3892.  
  3893. 0  No coverage
  3894. 1  Very light coverage
  3895. 2  Introductory coverage
  3896. 3  Good Coverage
  3897. 4  In-depth coverage
  3898. 5  Authoritative
  3899.  
  3900. /dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3901.  
  3902.  
  3903. ΓòÉΓòÉΓòÉ 9.6. Coming Up ΓòÉΓòÉΓòÉ
  3904.  
  3905. Coming Up 
  3906.  
  3907. I have here a trilogy of Warp API reference manuals, which I will review for 
  3908. next month (I said that last time, but I lied). Other books I would like to 
  3909. review are: 
  3910.  
  3911. OS/2 Presentation Manager GPI, 2nd edition, Winn
  3912. The Design of OS/2, 2nd Edititon, Kogan and Deitel
  3913.  
  3914. If anyone has a book they want to see reviewed, I will be happy to oblige. Just 
  3915. mail me and tell me. Publishers can send me books at the address on my personal 
  3916. page at the end of the magazine, and I will review all OS/2 development-related 
  3917. and advanced user books I receive. 
  3918.  
  3919. /dev/EDM2/BookReview - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  3920.  
  3921.  
  3922. ΓòÉΓòÉΓòÉ 10. Introduction to PM Programming ΓòÉΓòÉΓòÉ
  3923.  
  3924. Introduction to PM Programming 
  3925.  
  3926. Written by Larry Salomon, Jr. 
  3927.  
  3928. Introduction 
  3929.  
  3930. The purpose of this column is to provide the readers out there who are not 
  3931. familiar with PM application development the information necessary to satisfy 
  3932. their curiosity, educate themselves, and give them an advantage over the 
  3933. documentation supplied by IBM.  Of course, much of this stuff could probably be 
  3934. found in one of the many books out there, but the problem with books in general 
  3935. is that they don't answer the questions you have after you read the book the 
  3936. first time through. 
  3937.  
  3938. I will gladly entertain feedback from the readers about what was "glossed over" 
  3939. or what was detailed well, what tangential topics need to be covered and what 
  3940. superfluous crap should have been removed.  This feedback is essential in 
  3941. guaranteeing that you get what you pay for.  <grin> 
  3942.  
  3943. It should be said that you must not depend solely on this column to teach you 
  3944. how to develop PM applications; instead, this should be viewed as a supplement 
  3945. to your other information storehouses (books, the network conferences, etc.). 
  3946. Because this column must take a general approach, there will be some topics 
  3947. that you would like to see discussed that really do not belong here.  Specific 
  3948. questions can be directed to me via email and I will do my best to answer them 
  3949. in a timely fashion. 
  3950.  
  3951. Where Are We? 
  3952.  
  3953. As I sat down to write this month's installment, I had to look back to see 
  3954. where we've been.  The window classes that we've covered here so far are listed 
  3955. below: 
  3956.  
  3957.      Button (WC_BUTTON) 
  3958.      Entryfield (WC_ENTRYFIELD) 
  3959.      Listbox (WC_LISTBOX) 
  3960.      Menu (WC_MENU) 
  3961.      Static (WC_STATIC) 
  3962.      Titlebar (WC_TITLEBAR) 
  3963.  
  3964.  The window classes left to be covered are listed below: 
  3965.  
  3966.      Circular slider (WC_CIRCULARSLIDER) 
  3967.      Combo box (WC_COMBOBOX) 
  3968.      Container (WC_CONTAINER) 
  3969.      Frame (WC_FRAME) 
  3970.      Multi-line edit (WC_MLE) 
  3971.      Notebook (WC_NOTEBOOK) 
  3972.      Scroll bar (WC_SCROLLBAR) 
  3973.      Slider (WC_SLIDER) 
  3974.      Spin button (WC_SPINBUTTON) 
  3975.      Value set (WC_VALUESET) 
  3976.  
  3977.  As I looked, I decided that we could hit three birds with one stone if we 
  3978.  ventured into the realm of the circular slider, slider, and scrollbar, since 
  3979.  all three controls are very similar in function. 
  3980.  
  3981.  Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2 
  3982.  
  3983.  
  3984. ΓòÉΓòÉΓòÉ 10.1. Purpose ΓòÉΓòÉΓòÉ
  3985.  
  3986.  Purpose 
  3987.  
  3988. What is the purpose of each of these three controls?  To sum it up in one 
  3989. sentence, their purpose is to allow the user to choose a single value within a 
  3990. range of values.  Since Salomon's Law states that the complexity of a window 
  3991. class is exponentially proportional to the number of words in which you can 
  3992. state its purpose, you can imagine that we won't need to spend much time on 
  3993. these controls. 
  3994.  
  3995. Breakdown 
  3996.  
  3997. If you breakdown the capabilities of the controls, you will see that all three 
  3998. provide the following: 
  3999.  
  4000.      Set / Query the range of values 
  4001.      Set / Query the current value 
  4002.      Notify the owner when the value changes 
  4003.  
  4004.  We will look at the details specific to each control in this column starting 
  4005.  with the scroll bar (WC_SCROLLBAR). 
  4006.  
  4007.  Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2 
  4008.  
  4009.  
  4010. ΓòÉΓòÉΓòÉ 10.2. Scroll Bar Terminology ΓòÉΓòÉΓòÉ
  4011.  
  4012.  Scroll Bar Terminology 
  4013.  
  4014. The parts of a scroll bar are labelled in the illustration below. 
  4015.  
  4016. The buttons are used to change the position by one increment (see below). 
  4017.  
  4018. The slider areas are used to change the position by one page. 
  4019.  
  4020. The thumb is used to move the scroll bar to an absolute position. 
  4021.  
  4022. The concept of a unit or a page of units is defined by the application.  One 
  4023. unit may correspond to one line of text, but it may correspond to three lines 
  4024. of text. 
  4025.  
  4026. Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2 
  4027.  
  4028.  
  4029. ΓòÉΓòÉΓòÉ 10.3. Scroll Bar Styles ΓòÉΓòÉΓòÉ
  4030.  
  4031.  Scroll Bar Styles 
  4032.  
  4033. The scroll bar styles are listed below. 
  4034.  
  4035.      SBS_AUTOSIZE - The PM Guide and Reference states that this style causes 
  4036.       the scroll bar to automatically change its size to reflect the amount of 
  4037.       data contained in the window.  I have never seen the style used before 
  4038.       and there is no documentation on its use, so we will not discuss this 
  4039.       further. 
  4040.  
  4041.      SBS_AUTOTRACK - Like SBS_AUTOSIZE there is no documentation on this 
  4042.       style.  The PM Guide and Reference states that this style causes the 
  4043.       scroll bar to automatically scroll as more information is being displayed 
  4044.       on the screen. 
  4045.  
  4046.      SBS_HORZ - This style creates a horizontal scroll bar. 
  4047.  
  4048.      SBS_THUMBSIZE - This style indicates that a scroll bar control data 
  4049.       (SBCDATA) structure is being passed in as the second-to-last parameter to 
  4050.       WinCreateWindow() and that the cVisible and cTotal fields are 
  4051.       initialized. 
  4052.  
  4053.      SBS_VERT - This style creates a vertical scroll bar. 
  4054.  
  4055.  Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2 
  4056.  
  4057.  
  4058. ΓòÉΓòÉΓòÉ 10.4. Scroll Bar Notifications ΓòÉΓòÉΓòÉ
  4059.  
  4060.  Scroll Bar Notifications 
  4061.  
  4062. The scroll bar is unlike the other PM controls in that its notifications are 
  4063. not communicated via the WM_CONTROL message.  Instead, depending on the 
  4064. orientation of the scroll bar (horizontal or vertical), the owner receives a 
  4065. WM_HSCROLL or WM_VSCROLL message. 
  4066.  
  4067. WM_HSCROLL / WM_VSCROLL 
  4068.  
  4069. SHORT1FROMMP(mpParm1) - specifies the ID of the scroll bar. 
  4070.  
  4071. SHORT1FROMMP(mpParm2) - specifies the position of the scroll bar.  This is 0 if 
  4072. the keyboard is being used to move the scroll bar. 
  4073.  
  4074. SHORT2FROMMP(mpParm2) - notification type: 
  4075.  
  4076.      SB_LINELEFT - the left arrow was clicked with the mouse or the left arrow 
  4077.       key was pressed. 
  4078.  
  4079.      SB_LINERIGHT - the right arrow was clicked with the mouse or the right 
  4080.       arrow key was pressed. 
  4081.  
  4082.      SB_LINEUP - the up arrow was clicked with the mouse or the up arrow key 
  4083.       was pressed. 
  4084.  
  4085.      SB_LINEDOWN - the down arrow was clicked with the mouse or the down arrow 
  4086.       key was pressed. 
  4087.  
  4088.      SB_PAGELEFT - the slider was clicked to the left of the thumb with the 
  4089.       mouse or the page up key was pressed. 
  4090.  
  4091.      SB_PAGERIGHT - the slider was clicked to the right of the thumb with the 
  4092.       mouse or the page down key was pressed. 
  4093.  
  4094.      SB_PAGEUP - the slider was clicked above the thumb with the mouse or the 
  4095.       page up key was pressed. 
  4096.  
  4097.      SB_PAGEDOWN - the slider was clicked below the thumb with the mouse or 
  4098.       the page down key was pressed. 
  4099.  
  4100.      SB_SLIDERPOSITION - this is sent to indicate the final position of the 
  4101.       scroll bar. 
  4102.  
  4103.      SB_SLIDERTRACK - if the mouse is being used to "drag" the thumb, this is 
  4104.       sent every time the position changes. 
  4105.  
  4106.      SB_ENDSCROLL - this indicates the end of scrolling and is sent only if 
  4107.       the thumb was not dragged. 
  4108.  
  4109.  Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2 
  4110.  
  4111.  
  4112. ΓòÉΓòÉΓòÉ 10.5. Scroll Bar Messages ΓòÉΓòÉΓòÉ
  4113.  
  4114.  Scroll Bar Messages 
  4115.  
  4116. There are five, easy to understand messages that the scroll bar understands: 
  4117.  
  4118. SBM_QUERYPOS 
  4119.  
  4120. This message returns the current position. 
  4121.  
  4122. SHORT1FROMMR(mrResult) - current position. 
  4123.  
  4124. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  4125.  
  4126. SBM_QUERYRANGE 
  4127.  
  4128. This message returns the current scroll bar range. 
  4129.  
  4130. SHORT1FROMMR(mrResult) - lower bound of the range. 
  4131.  
  4132. SHORT2FROMMR(mrResult) - upper bound of the range. 
  4133.  
  4134. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  4135.  
  4136. SBM_SETPOS 
  4137.  
  4138. This message sets the current position. 
  4139.  
  4140. SHORT1FROMMP(mpParm1) - new position. 
  4141.  
  4142. SHORT1FROMMR(mrResult) - success indicator (BOOL). 
  4143.  
  4144. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  4145.  
  4146. SBM_SETSCROLLBAR 
  4147.  
  4148. This message sets the current position and the range. 
  4149.  
  4150. SHORT1FROMMP(mpParm1) - new position. 
  4151.  
  4152. SHORT1FROMMP(mpParm2) - new lower bound of the range. 
  4153.  
  4154. SHORT2FROMMP(mpParm2) - new upper bound of the range. 
  4155.  
  4156. SHORT1FROMMR(mrResult) - success indicator (BOOL). 
  4157.  
  4158. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  4159.  
  4160. SBM_SETTHUMBSIZE 
  4161.  
  4162. This message sets the size of the thumb.  It is used to indicate to the user 
  4163. how much of the data is viewable at a time. 
  4164.  
  4165. SHORT1FROMMP(mpParm1) - visible amount of data. 
  4166.  
  4167. SHORT2FROMMP(mpParm1) - total amount of data. 
  4168.  
  4169. SHORT1FROMMR(mrResult) - success indicator (BOOL). 
  4170.  
  4171. Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2 
  4172.  
  4173.  
  4174. ΓòÉΓòÉΓòÉ 10.6. Next Month ΓòÉΓòÉΓòÉ
  4175.  
  4176.  Next Month 
  4177.  
  4178. Next month we will take a look at a small application that uses both the 
  4179. horizontal and vertical scroll bars to allow you to scroll through a "large" 
  4180. amount of data.  Bring your thinking caps! 
  4181.  
  4182. Introduction to PM Programming - EDM/2 - Nov 1995 - Volume 3, Issue 2 
  4183.  
  4184.  
  4185. ΓòÉΓòÉΓòÉ 11. OOPS Avenue ΓòÉΓòÉΓòÉ
  4186.  
  4187. OOPS Avenue 
  4188.  
  4189. Prolog 
  4190.  
  4191. Well Larry finally thought it was safe to let me do an editorial section as a 
  4192. preface to the column.  So with out further adieu, here we go. 
  4193.  
  4194. I was going to start this new section off with a bang by dragging Watcom's 
  4195. technical support system through the coals.  A general rule is never write 
  4196. anything that you intend to have someone else read while your angry.  During 
  4197. the cool down period, much to my surprise, I received a phone call from Watcom 
  4198. tech support, explaining the initial lousy support I had received.  Although 
  4199. tech support couldn't offer any solution, the bug which I had reported was 
  4200. confirmed to be a known problem that affects only some people for unknown 
  4201. reasons.  In the Watcom 10.5 compiler review, you will notice that I mentioned 
  4202. the debugger didn't debug PM programs. 
  4203.  
  4204. After trying to compile a public domain C++ package with Watcom, Metaware and 
  4205. C-Set++ 2.1, I suddenly realized just how buggy C++ compilers are.  Each one of 
  4206. the three compilers complained about a different section of the code. With 
  4207. Metaware and Watcom it was problems with templates.  With C-Set++, it was an 
  4208. incredibly strange interpretation of access permissions.  After some hacking 
  4209. about with the code, it finally compiled cleanly on all 3 compilers. Hopefully, 
  4210. when compiler vendors start writing to the ANSI C++ specification, these 
  4211. problems will start disapearing. 
  4212.  
  4213. OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  4214.  
  4215.  
  4216. ΓòÉΓòÉΓòÉ 11.1. Introduction ΓòÉΓòÉΓòÉ
  4217.  
  4218.  Introduction 
  4219.  
  4220. Direct To SOM (DTS) is the easiest way to write a SOM object.  A DTS compiler 
  4221. compiles code in its native language (i.e. C++) into a SOM compatible module. 
  4222. The two DTS C++ compilers for OS/2 are Metaware High C/C++ and Visual Age C++. 
  4223. This article will use the Metaware compiler.  However, IBM's DTS #pragma syntax 
  4224. will be used so this examples should (in theory) compile under VAC. 
  4225.  
  4226. The use of DTS will be illustrated by designing a simple screen saver object. 
  4227. In this issue, we will design an OOP saver module in C++, and DTS. The OOP 
  4228. method will then be compared to a conventional non-OOP approach. 
  4229.  
  4230. OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  4231.  
  4232.  
  4233. ΓòÉΓòÉΓòÉ 11.2. A C++ Saver Object ΓòÉΓòÉΓòÉ
  4234.  
  4235.  A C++ Saver Object 
  4236.  
  4237. Before we can design an object, we have to decide what properties the object 
  4238. needs.  We need to be able to toggle the saver object in and out of saver mode, 
  4239. and possibly display some setup information.  The following C++ object could 
  4240. serve as the base for our hierarchy. 
  4241.  
  4242. class SaverBase{
  4243.    public:
  4244.       SaverBase();
  4245.       ~SaverBase();
  4246.  
  4247.       virtual void  StartSaver()=0;
  4248.       virtual void  StopSaver()=0;
  4249.  
  4250.       virtual void  DisplaySetup(){}
  4251.  
  4252. };
  4253.  
  4254. To implement a specific screen saver, we would subclass SaverBase and implement 
  4255. the two pure virtual member functions.  We could even create a non-member 
  4256. function to create a specific class and then package each child of SaverBase in 
  4257. a DLL.  This would allow us to add new saver types without recompiling the 
  4258. code.  However, anyone wanting to write new saver modules would have to use the 
  4259. exact same C++ compiler as we used.  The need to use the exact same compiler 
  4260. severely limits the usefulness of using a C++ based OOP approach. 
  4261.  
  4262. OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  4263.  
  4264.  
  4265. ΓòÉΓòÉΓòÉ 11.3. A DTS Saver Object ΓòÉΓòÉΓòÉ
  4266.  
  4267.  A DTS Saver Object 
  4268.  
  4269. The best part of using a DTS based approach is that we can write C++ code and 
  4270. let the compiler worry about the SOM details.  There are a few differences 
  4271. between DTS C++ and native C++.  These differences are listed in the DTS 
  4272. section of the DTS compiler.  Thus, we won't go into them here unless they 
  4273. directly affect the example. 
  4274.  
  4275. Various aspects of how the C++ object is converted into a SOM object are 
  4276. controlled by pragmas.  The pragmas in the following DTS based saver class are 
  4277. numbered.  These numbers will be used when explaining what each pragma does. 
  4278.  
  4279. #pragma SOMAsDefault(on)                                                                  //(1)
  4280.  
  4281. class SaverModule{
  4282.    #pragma SOMClassVersion(*,1,1)                                                         //(2)
  4283.    #pragma SOMNoMangling(on)                                                              //(3)
  4284.    #pragma SOMClassName(*,"SaverModule")                                                  //(4)
  4285.  
  4286. public:
  4287.    SaverModule();
  4288.    ~SaverModule();
  4289.  
  4290.    virtual int    GetNumPages();
  4291.    virtual void   ActivateSaver();
  4292.    virtual void   DeactivateSaver();
  4293.  
  4294.    #pragma SOMNoMangling(pop)                                                             //(5)
  4295.    #pragma SOMReleaseOrder(GetNumPages(),ActivateSaver(),DeactivateSaver(),operator=)     //(6)
  4296. private:
  4297.  
  4298. };
  4299.  
  4300. #pragma SOMAsDefault(pop)                                                                 //(7)
  4301.  
  4302.  #pragma Number      Effect 
  4303.  1                   Turn on C++ -> SOM mode.  Any C++ object declaration 
  4304.                      occurring after this pragma will be assumed to be a DTS 
  4305.                      object. 
  4306.  2                   Specify the class version numbers. 
  4307.  3                   Turn off name mangling.  This makes it easier for non-DTS 
  4308.                      programmers to extend this object in the language of their 
  4309.                      choice. 
  4310.  4                   Specify the name of the SOM class.  To avoid mangling the 
  4311.                      SOM classes name, we specify the name the DTS compiler is 
  4312.                      to use. 
  4313.  5                   Restore name mangling to its setting before pragma number 
  4314.                      3. This is done so that the DTS compiler doesn't create a 
  4315.                      "__as" function in the .idl.  The leading "_" cases the 
  4316.                      SOM compiler (sc) to generate a bunch of error messages. 
  4317.  6                   Specify the release order for the functions.  Note:  the 
  4318.                      default constructor and destructor are automatically 
  4319.                      included in the release order so they don't have to be 
  4320.                      included.  Also note that operator= is automatically 
  4321.                      generated by the DTS compiler. 
  4322.  
  4323.  The DTS object "SaverModule", closely resembles the C++ saver module. There 
  4324.  are functions to start and stop the saver, and one to get the number of setup 
  4325.  pages for the module.  Assuming we were to implement the configuration of the 
  4326.  saver modules in a notebook, we would need to be able to query the number of 
  4327.  pages and the page handles from the module.  For now, we'll ignore the issue 
  4328.  of configurability.  We'll explore this issue in more detail when we revisit 
  4329.  the design in subsequent issues. 
  4330.  
  4331.  One of the best features of C++ DTS compilers is the ability to easily mix C++ 
  4332.  and DTS objects.  In the following example, we subclass SaverModule to 
  4333.  illustrate how a saver type can be created.  We will use a C++ thread library 
  4334.  to implement the threading of the DTS object.  The following DTS object 
  4335.  illustrates how a saver object would work and how to mix C++ objects with DTS 
  4336.  objects. 
  4337.  
  4338.   #pragma SOMAsDefault(off)
  4339.   #include <ThreadTemp.h>
  4340.   #pragma SOMAsDefault(pop)
  4341.  
  4342.   #include "Saver.hh"
  4343.  
  4344.   #pragma SOMAsDefault(on)
  4345.  
  4346.   class TestSaver : public SaverModule{
  4347.      #pragma SOMClassVersion(*,1,1)
  4348.      #pragma SOMNoMangling(*)
  4349.      #pragma SOMClassName(*,"TestSaver")
  4350.  
  4351.  
  4352.   public:
  4353.      TestSaver();
  4354.      ~TestSaver();
  4355.  
  4356.      int    GetNumPages();
  4357.      void   ActivateSaver();
  4358.      void   DeactivateSaver();
  4359.  
  4360.      #pragma SOMNoMangling(pop)
  4361.  
  4362.   private:
  4363.      void  ThreadFnc(void);
  4364.  
  4365.      ClassThreadwoArg<TestSaver>
  4366.            TestThread;                               //(1)
  4367.  
  4368.      int   SaverActive;
  4369.   };
  4370.  
  4371.   #pragma SOMAsDefault(pop)
  4372.  
  4373.  When ActivateSaver is called, TestThread is started.  While the saver is 
  4374.  active, it writes '.'  to stdout.  The interesting part about this example, is 
  4375.  that a C++ object is a member of a DTS object and that a DTS object is used as 
  4376.  the "type" of a C++ template object (see number 1 in the above source). Below, 
  4377.  we see that using a DTS object is the same as using a C++ object. 
  4378.  
  4379.   #include <io.h>
  4380.   #include <conio.h>
  4381.   #include <iostream.h>
  4382.  
  4383.   #include "TstSave.hh"
  4384.  
  4385.   int main(){
  4386.      SaverModule *Saver;
  4387.  
  4388.      cout<<"Press Enter to start saver"<<endl;
  4389.      getch();
  4390.  
  4391.      Saver=new TestSaver;
  4392.      Saver->ActivateSaver();
  4393.  
  4394.      (cout<<"Press Enter to stop saver"<<endl).flush();
  4395.      getch();
  4396.  
  4397.      Saver->DeactivateSaver();
  4398.  
  4399.      cout<<"Press Enter to destroy saver"<<endl;
  4400.      getch();
  4401.  
  4402.      delete Saver;
  4403.  
  4404.  
  4405.   return 0;
  4406.   }
  4407.  
  4408.  Notice that in this example, we have to know about the object's "type" before 
  4409.  we can use it.  This makes it impossible to add new saver types at run time. 
  4410.  However, SOM was designed to allow run time class resolution and much much 
  4411.  more.  We'll explore run time class loading next.  But before we move on, the 
  4412.  full source to this sample can be found in try1.zip. 
  4413.  
  4414.  To support run time loading, we have to put our objects into one or more DLLs. 
  4415.  In doing so, I stumbled into a Metaware bug.  It seems one can't use the 
  4416.  threaded libraries with a DLL.  If you try to use the multi-threaded 
  4417.  libraries, the DLL will trap on load.  This required all the threading code to 
  4418.  be removed from the DTS objects. 
  4419.  
  4420.  The files main.cpp and maincpp.cpp illustrate that the DTS DLL is indeed 
  4421.  usable from 2 different languages/compilers.  Below is the source code to 
  4422.  main.cpp, which illustrates dynamically loading a DTS object from a DTS 
  4423.  program. 
  4424.  
  4425.   #include <io.h>
  4426.   #include <conio.h>
  4427.   #include <iostream.h>
  4428.  
  4429.   #include <som.hh>
  4430.   #include <somcls.hh>
  4431.   #include <somcm.hh>
  4432.  
  4433.   //#include "Saver.hh"
  4434.   #include "TstSave.hh"
  4435.  
  4436.   int main(){
  4437.      SaverModule *Saver;
  4438.  
  4439.      cout<<"Press Enter to start saver"<<endl;
  4440.      getch();
  4441.  
  4442.  
  4443.      somId classId = somIdFromString("TestSaver");                        //(1)
  4444.      SOMClass *myClass = SOMClassMgrObject->somFindClsInFile(classId,
  4445.                            1, 1,"TstSave");                               //(2)
  4446.  
  4447.      SOMFree(classId);                                                    //(3)
  4448.  
  4449.      Saver=(SaverModule *) myClass->somNew();                             //(4)
  4450.   //   Saver=new TestSaver;                                               //(5)
  4451.      Saver->ActivateSaver();
  4452.  
  4453.      (cout<<"Press Enter to stop saver"<<endl).flush();
  4454.      getch();
  4455.  
  4456.      Saver->DeactivateSaver();
  4457.  
  4458.      cout<<"Press Enter to destroy saver"<<endl;
  4459.      getch();
  4460.  
  4461.      delete Saver;
  4462.  
  4463.  
  4464.   return 0;
  4465.   }
  4466.  
  4467.  Note:  even though "TstSave.hh" is included, it doesn't have to be. 
  4468.  
  4469.  The to dynamically load a SOM object, lines 1 through 4 replace line 5. To use 
  4470.  the DTS object with C++ bindings, simply change the ".hh" to ".xh" in the 
  4471.  include statements.  The file try2.zip contains the source for the dynamic 
  4472.  loading sample 
  4473.  
  4474.  You're probably wondering where did these .xh files come from.  To allow DTS 
  4475.  objects to be used from other languages, the DTS compiler can create .idl 
  4476.  files.  Using the SOM compiler, one can create bindings for any language. 
  4477.  
  4478.  OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  4479.  
  4480.  
  4481. ΓòÉΓòÉΓòÉ 11.4. The Non-OOP Method of Creating an Extendible Screen Saver ΓòÉΓòÉΓòÉ
  4482.  
  4483.  The Non-OOP Method of Creating an Extendible Screen Saver 
  4484.  
  4485. The term "Non-OOP" is misleading.  Perhaps the a better term is informal OOP. 
  4486. In essence what the developer is doing is using DLLs to implement a limited 
  4487. form of data-abstraction.  The developer defines a set of mandatory functions 
  4488. that the DLL must implement.  The screen saver executable then uses 
  4489. DosLoadModule and DosQueryProcAddr to load and execute the saver functions. 
  4490.  
  4491. In either of the OOP cases, the addresses of the saver functions aren't queried 
  4492. by the saver executable.  In the DTS version, saver modules themselves can be 
  4493. subclassed to alter their behavior. 
  4494.  
  4495. OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  4496.  
  4497.  
  4498. ΓòÉΓòÉΓòÉ 11.5. Summary ΓòÉΓòÉΓòÉ
  4499.  
  4500.  Summary 
  4501.  
  4502. DTS is an easy way for someone familar with C++ to create SOM objects.  It 
  4503. allows one to easily mix C++ and SOM objects with each other.  This allows the 
  4504. best of both worlds:  C++ can be used where raw speed is required, and SOM can 
  4505. be used where binary independence is needed.  In subsequent issues, I hope to 
  4506. develop the DTS Screen saver into a working program. 
  4507.  
  4508. OOPS Avenue - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  4509.  
  4510.  
  4511. ΓòÉΓòÉΓòÉ 12. Contributors to this Issue ΓòÉΓòÉΓòÉ
  4512.  
  4513. Are You a Potential Author? 
  4514.  
  4515. We are always looking for (new) authors.  If you have a topic about which you 
  4516. would like to write, send a brief description of the topic electronically to 
  4517. any of the editors, whose addresses are listed below, by the 15th of the month 
  4518. before the month in which your article will appear.  This alerts us that you 
  4519. will be sending an article so that we can plan the issue layout accordingly. 
  4520. After you have done this, get the latest copy of the Article Submission 
  4521. Guidelines from hobbes.nmsu.edu in the /os2/newsltr directory.  (The file is 
  4522. artsub.zip.) The completed text of your article should be sent to us no later 
  4523. than five days prior to the last day of the month; any articles received after 
  4524. that time may be pushed to the next issue. 
  4525.  
  4526. The editors can be reached at the following email addresses: 
  4527.  
  4528.      Larry Salomon - os2man@panix.com (Internet). 
  4529.      Carsten Whimster - bcrwhims@uwaterloo.ca (Internet). 
  4530.  
  4531.  The following people contributed to this issue in one form or another (in 
  4532.  alphabetical order): 
  4533.  
  4534.      Marc Mittelmeijer 
  4535.      Dean Roddey 
  4536.      Larry Salomon, Jr. 
  4537.      Eric Slaats 
  4538.      Carsten Whimster 
  4539.      Gordon Zeglinski 
  4540.      Network distributors 
  4541.  
  4542.  Contributors - EDM/2 - Nov 1995 - Volume 3, Issue 9 
  4543.  
  4544.  
  4545. ΓòÉΓòÉΓòÉ 12.1. Marc Mittelmeijer ΓòÉΓòÉΓòÉ
  4546.  
  4547. Marc Mittelmeijer 
  4548.  
  4549. Marc Mittelmeijer studied mathematics at the faculty Mathematics and 
  4550. Informatics at the Technical University of Eindhoven.  Since 1984 Marc teaches 
  4551. mathematics and information technology at the Hogeschool Eindhoven, Faculty 
  4552. Economics Sr Business Informatics.  Besides teaching he is researching the 
  4553. behavior of neural networks in a financial environment. 
  4554.  
  4555. Marc can be reached at M.Mittelmeijer@fe.hse.nl 
  4556.  
  4557. Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9 
  4558.  
  4559.  
  4560. ΓòÉΓòÉΓòÉ 12.2. Dean Roddy ΓòÉΓòÉΓòÉ
  4561.  
  4562. Dean Roddey 
  4563.  
  4564. Dean Roddey is a Senior Software Engineer at Quantitative Medicine, A Marquette 
  4565. Electronics Company, in Annapolis MD.  He is also the author of the CIDLib 
  4566. Class Libraries, a C++ class framework for Warp and IBM's Visual Age C++ 
  4567. development environment.  He can be reached at droddey@jaguNet.com or at 
  4568. Compuserve id 72170,1614.  Or check out his home page at 
  4569. http://www.jagunet.com/~droddey/ to get more information on the CIDLib 
  4570. libraries. 
  4571.  
  4572. Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9 
  4573.  
  4574.  
  4575. ΓòÉΓòÉΓòÉ 12.3. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
  4576.  
  4577. Larry Salomon Jr. 
  4578.  
  4579. Larry Salomon Jr. has been developing OS/2 applications since version 1.1 in 
  4580. 1989.  He has written numerous applications, including the Scramble applet that 
  4581. was included in OS/2 versions 2.0-2.11, and the I-Brow, Magnify, and Screen 
  4582. Capture trio that has been distributed on numerous CD-ROMs. 
  4583.  
  4584. Larry is also the coauthor of the successful book, The Art of OS/2 Warp 
  4585. Programming (Wiley-QED).  Finally, he is the CEO/President of IQPac Inc. which 
  4586. is responsible for the publication of EDM/2 and he is a frequent contributor to 
  4587. the publication. 
  4588.  
  4589. Larry can be reached electronically via the Internet at os2man@panix.com. 
  4590.  
  4591. Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9 
  4592.  
  4593.  
  4594. ΓòÉΓòÉΓòÉ 12.4. Eric Slaats ΓòÉΓòÉΓòÉ
  4595.  
  4596. Eric Slaats 
  4597.  
  4598. Eric Slaats teaches information technology at the Hogeschool Eindhoven, Faculty 
  4599. Economics Sr Business Informatics.  Besides teaching he has written a number of 
  4600. books.  Currently he is researching the behavior of neural networks in a 
  4601. financial environment.  He started programming OS/2 PM to build an interface 
  4602. for a Neural network problem in september 1994.  He's the author of the Smalled 
  4603. and Confed utilities. 
  4604.  
  4605. Eric can be reached electronically via the internet at E.Slaats@fe.hse.nl 
  4606.  
  4607. Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9 
  4608.  
  4609.  
  4610. ΓòÉΓòÉΓòÉ 12.5. Carsten Whimster ΓòÉΓòÉΓòÉ
  4611.  
  4612. Carsten Whimster 
  4613.  
  4614. Carsten is an undergraduate Computer Science student at the University of 
  4615. Waterloo. He is currently in fourth year, and enjoying it immensely. He uses 
  4616. Watcom C/C++ 10.0a and Watcom VX-REXX 2.0c.  Carsten is the author of some 
  4617. commandline utilities, and POV-Panel/2.  He is currently trying to learn enough 
  4618. GPI programming to do a remake of the old video game Qix, but there are other 
  4619. projects on the go too, such as converting POV-Panel/2 to PM, and writing a PM 
  4620. ps type utility. Carsten is also a TEAM-OS/2 member, and has adopted a little 
  4621. computer store called The Data Store in Waterloo, Ontario. 
  4622.  
  4623. You may reach Carsten... 
  4624.  
  4625.  ...via email (Internet): 
  4626.  
  4627. bcrwhims@undergrad.math.uwaterloo.ca 
  4628.  
  4629.  ...via the World Wide Web: 
  4630.  
  4631. http://www.undergrad.math.uwaterloo.ca/~bcrwhims/ 
  4632.  
  4633.  ...via snail mail: 
  4634.  
  4635. 318A Spruce Street 
  4636. Waterloo, Ontario 
  4637. Canada 
  4638. N2L 3M7 
  4639.  
  4640.  ...via voice: 
  4641.  
  4642. (519)886-2439 
  4643.  
  4644. Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9 
  4645.  
  4646.  
  4647. ΓòÉΓòÉΓòÉ 12.6. Gordon Zeglinski ΓòÉΓòÉΓòÉ
  4648.  
  4649. Gordon Zeglinski 
  4650.  
  4651. Gordon Zeglinski is a freelance programmer/consultant who received his Master's 
  4652. degree in Mechanical Engineering with a thesis on C++ sparse matrix objects. 
  4653. He has been programming in C++ for 6 years and also has a strong background in 
  4654. FORTRAN.  He started developing OS/2 applications with version 2.0 . 
  4655.  
  4656. His current projects include a client/server communications program that 
  4657. utilitizes OS/2's features which has entered beta testing.  Additionally, he is 
  4658. involved in the development of a "real-time" automated vehicle based on OS/2 
  4659. and using C++ in which he does device driver development and designs the 
  4660. applications that comprise the control logic and user interface. 
  4661.  
  4662. He can be reached via the Internet at zeglins@cc.umanitoba.ca. 
  4663.  
  4664. Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9 
  4665.  
  4666.  
  4667. ΓòÉΓòÉΓòÉ 12.7. Network Distributors ΓòÉΓòÉΓòÉ
  4668.  
  4669. Network Distributors 
  4670.  
  4671. These people are part of our distribution system to provide EDM/2 on networks 
  4672. other than the Internet.  Their help to provide access to this magazine for 
  4673. others is voluntary and we appreciate them a lot! 
  4674.  
  4675.      Paul Hethmon (phethmon@utk.edu) - Compuserve 
  4676.      Gess Shankar (gess@knex.mind.org) - Internet 
  4677.      Jason B. Tiller (PeerGynt@aol.com) - America On-line 
  4678.      David Singer (singer@almaden.ibm.com) - IBM Internal 
  4679.      Jesper Nielsen (afdata@pop02.ny.us.ibm.net) - Denmark BBS's 
  4680.  
  4681.  If you would like to become a "network distributor", be sure to contact the 
  4682.  editors so that we can give you the credit you deserve! 
  4683.  
  4684.  Contributors - EDM/2 - Oct 1995 - Volume 3, Issue 9